zoukankan      html  css  js  c++  java
  • [积累]C++复习 海大2014硕士生面试题微信系统总结

    好久没用C++了,正好同学有个面试题,于是就帮忙看了一下.尽管对C++的知识了解不少, 可是长期被Java浸淫, 发现这个简单的程序却也写着也不是那么顺手.好在最后还是搞定了,以下分析一下,题目例如以下, 小弟不才, 可能有错误的地方 ,还请大神指正
    这里写图片描写叙述

    把这个题目分成了Group, User ,WechatServer三个类, 详细就是一点简单的操作, 后面将附上源代码.这里记录一下自己写时候遇到问题的一些总结:

    1.实现单例, 这和Java差距还是有些的. WechatServer须要一个单例, 这样能够保持User列表,和group列表,
    代码实现例如以下:

    class WechatServer{
        private:
            WechatServer(){}
            static WechatServer* m_Instance;
            vector<User*> mUsers;
            vector<Group*> mGroups;
        public:
    
            //need use singleton
            static WechatServer* GetInstance()//这里使用了饿汉式
            {
                if(!m_Instance)
                    m_Instance = new WechatServer();
                return m_Instance;
            }
            User* findUserById(int id); //这些函数在WechatServer.cpp中实现, 当然事实上能够在不论什么一个include了WechatServer.h的cpp文件里实现 .cpp文件只是是为了让代码更加模块化
            vector<User*> getUsers();
            void createGroup(vector<User*> users , int creatorId);
            void addUser(User* user);
    };

    2.互相include问题, 这里遇到两个问题

    A 反复编译问题, 编译的时候, User 和 Group互相include了, 開始的时候,发现编译器编译到这里死循环了,也好理解
    编译Group的时候因为include了User就去先编译User,可是编译User的时候有发现include了Group也是去编译Group…
    解决方式当然非常easy. 參考 http://yuanzhifei89.iteye.com/blog/2020082
    把代码放到以下的代码块中:

    #ifndef _Group_H
    #define _Group_H
    //防止嵌套include导致编译死循环
    #endif 

    B 这时候编译Group的时候发现找不到User类了, 原因先编译Group的时候,User类没有编译处理, 所以做了一个前置声明解决这个问题
    总体代码

    #ifndef _Group_H
    #define _Group_H
    //防止嵌套include导致编译死循环
    
    #include <iostream>
    #include <vector>
    //#include "User.h"
    using namespace std;
    class User;//这里是C++类的前向声明。没实用include“User.h”
               //编译到一块之后User*自然指向了User class
                //事实上非常easy, 是先编译了Group又编译了User, 最后编译了WechatServer, 依照字母顺序
                //所以User也能够前向声明一个class WechatServer
    class Group{
    public:
        int mGroupId,mCreatorId;
        vector<User*> mMembers;
        Group(int groupId , int creatorId){
          mGroupId = groupId;
          mCreatorId = creatorId;
        }
        void addMembers(vector<User*> users){
            for (vector<User*>::size_type i = 0; i != users.size(); ++i)
            {
                mMembers.push_back(users[i]);
            }
        }
    
    };
    
    #endif

    3. C++特有符号
    符号:: 能够觉得限定搜索范围, 假设想在User.cpp中实现User.h中声明的getId()函数,或者使用User.h声明的mFriends私有成员变量必须这么写: 没有User::会报错.同一时候, 事实上在main.cpp中实现这个函数也没有不论什么问题 .h真正包括了类,cpp只是是 他们的实现而已, 里面的内容能够写在不论什么地方

     User.h:
          int mWeChatId;
    
     User.cpp:
         int User::getId(){return User::mWechatId} 
    

    符号”.” : 这是C++的对象调用函数使用的, 也说明类只是是struct的延伸

    符号 -> : 指针调用函数使用

    & 和 * : 地址和指针
    &作用在一个对象和基本类型签名, 是取这个对象/类型的地址, 事实上这个地址就是指针用到的, 所以能够给指针赋值:

        User user;//真正赋值到内存了
        user.getId();
    
        User* uptr = &user;//地址就是指针
        uptr->getId();

    另外&用在函数中还有传递引用的左右,

    int p = 8;
    test(int &i){
        i = 88;
    }
    test(p);// p = 88

    4.堆和栈
    在这个问题中new了八个User, 開始把User放到了栈中, 结果他们的地址都是一个.后来放到堆中解决.

    //User user(1000 + i, 84508241+ i , phone , email);
    //cout<<&user; 这样放到了栈中, 这里尽管循环了八次, 可是打印出来的地址事实上都是同一个
    //须要把user放到堆中, 这样才干够生成八个User
    User* user = new User(1000 + i, 84508241+ i , phone , email);
    cout << user;
    wechatServer->addUser(user);

    5.vector的遍历

    void addFreind(User* user ,vector<User*> userlist){
        int friendCount = 0;
        for (vector<User*>::size_type i = 0; i != userlist.size(); ++i)
        {
            User* myfriend = userlist[i];
            //can not add myself
            if(myfriend->getId() != user->getId() && friendCount < 5){
                cout << "adding friend : "<< myfriend->getId()<<endl;
                user->addFriend(myfriend);
                friendCount ++;
            }
        }
    }

    6.const
    相似java中的final, 不可变
    參考http://cnmtjp.blog.51cto.com/204390/35976

    void f(const int i) { .........}
          //对传入的參数进行类型检查。不匹配进行提示
    void f(const int i) { i=10;//error! }
          //假设在函数体内改动了i,编译器就会报错

    const 函数

    修饰类成员函数
    void func() const; // const成员函数中不同意对数据成员进行改动。假设改动,编译器将报错。假设某成员函数不须要对数据成员进行改动,最好将其声明为const 成员函数,这将大大提高程序的健壮性。

    const 为函数重载提供了一个參考 class A { public: void func(); // [1]:一个函数 void func() const; // [2]:上一个函数[1]的重载 …… }; A a(10); a.func(); // 调用函数[1] const A b(100); //const的变量调用const的函数 b.func(); // 调用函数[2]

    项目git地址 https://git.oschina.net/sfshine/CppDemoWechat.git
    IDE :QTCreator 2.4.1

  • 相关阅读:
    Maven的配置文件-settings.xml内容分解
    数据库管理工具-Navicat Premium 12
    转:android Support 兼容包详解
    转:聊聊mavenCenter和JCenter
    转:serialVersionUID作用
    Android 6.0 权限知识学习笔记
    X86和X86_64和X64有什么区别?
    Android 问题汇总(持续更新)
    Android-armebi-v7a、arm64-v8a、armebi的坑
    HttpUrlConnection 基础使用
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5138440.html
Copyright © 2011-2022 走看看