[積累]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…
解決方案當然很簡單. 參考 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

發佈了400 篇原創文章 · 獲贊 14 · 訪問量 86萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章