现在的位置: 首页 > 综合 > 正文

[积累]C++复习 海大2014硕士生面试题微信系统总结

2019年06月10日 ⁄ 综合 ⁄ 共 3399字 ⁄ 字号 评论关闭

好久没用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…
解决方案当然很简单. 参考 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
            //其实很简单, 是先编译了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

抱歉!评论已关闭.