1.友元类
#include <iostream>
using namespace std;
class TV // 电视机
{
private:
bool mState = false; // true:开 false:关
int mProgramIndex = 0; // 节目索引
public:
friend class RemoteController; // 友元类,友元类可以访问当前类的私有内容
bool getState();
int getProgramIndex();
};
bool TV::getState()
{
return mState;
}
int TV::getProgramIndex()
{
return mProgramIndex;
}
class RemoteController // 遥控器
{
public:
void setState(TV &tv)
{
tv.mState = !tv.mState;
}
void setProgramIndex(TV &tv, int programIndex)
{
if(tv.mState)
{
tv.mProgramIndex = programIndex;
}
else
{
cerr << "电视机未打开,无法设置频道." << endl;
}
}
};
int main(int argc, const char * argv[]) {
// 友元类
TV tv;
RemoteController remoteController;
remoteController.setState(tv);
remoteController.setProgramIndex(tv, 12);
cout << "开关机状态:" << ((tv.getState())?"开机":"关机") << endl; // 开机
cout << "频道:" << tv.getProgramIndex() << endl; // 12
return 0;
}
2.友元成员方法
将某一个类的某些方法单独设为另外一个类的友元方法
#include <iostream>
using namespace std;
/*
在一个类中使用另外一个类的两种情况:
1. 只是引用 void setState(TV &tv) TV只需要在前面声明即可
2. 访问了类型中的成员 类型必须在前面定义(具体实现里面的内容)
*/
//第3步 声明TV以配合RemoteController
class TV;
//第2步 RemoteController需要在TV前面声明,否则编译器会因为找不到RemoteController报错
class RemoteController
{
public:
void setState(TV &tv); // 这里的TV要求Class TV在前面,二者矛盾
// 如果方法在类的内部实现的话就涉及到了访问类中成员,那就不是一个class TV;能解决的了
// 所以方法的声明写在这里,方法的定义要写在Class TV的后面,才不会报错,方法的定义就要使用inline关键字了
void setProgramIndex(TV &tv, int programIndex);
void process(TV &tv);
};
class TV
{
private:
bool mState = false; // true:开 false:关
int mProgramIndex = 0; // 节目索引
public:
// 第1步 声明友元成员方法
friend void RemoteController::setState(TV &tv); // 这里要求RemoteController在前面
friend void RemoteController::setProgramIndex(TV &tv, int programIndex);
bool getState();
int getProgramIndex();
};
bool TV::getState()
{
return mState;
}
int TV::getProgramIndex()
{
return mProgramIndex;
}
//第4步,RemoteController的方法实现中因为涉及到了访问类型中成员,所以
//
inline void RemoteController::setState(TV &tv)
{
tv.mState = !tv.mState;
}
inline void RemoteController::setProgramIndex(TV &tv, int programIndex)
{
if(tv.mState)
{
tv.mProgramIndex = programIndex;
}
else
{
cerr << "电视机未打开,无法设置频道." << endl;
}
//tv.mState = 20;
}
void RemoteController::process(TV &tv)
{
// tv.mState = 20; //报错,因为这个方法不是TV类的友元方法,无法访问TV类中的私有成员
}
int main(int argc, const char * argv[]) {
// 友元成员方法
// remoteController中的两个方法是TV中的友元方法,这两个方法可以调用TV中的私有内容
TV tv;
RemoteController remoteController;
remoteController.setState(tv);
remoteController.setProgramIndex(tv, 12);
cout << "开关机状态:" << ((tv.getState())?"开机":"关机") << endl;
cout << "频道:" << tv.getProgramIndex() << endl;
return 0;
}
3.互为友元类
#include <iostream>
using namespace std;
class RemoteController;
class TV
{
private:
bool mState = false; // true:开 false:关
int mProgramIndex = 0; // 节目索引
public:
friend class RemoteController;
bool getState();
int getProgramIndex();
void reply(RemoteController &rc);
};
bool TV::getState()
{
return mState;
}
int TV::getProgramIndex()
{
return mProgramIndex;
}
class RemoteController
{
private:
string mAudioStr;
public:
friend class TV;
void setState(TV &tv)
{
tv.mState = !tv.mState;
}
void setProgramIndex(TV &tv, int programIndex)
{
if(tv.mState)
{
tv.mProgramIndex = programIndex;
}
else
{
cerr << "电视机未打开,无法设置频道." << endl;
}
}
};
void TV::reply(RemoteController &rc)
{
rc.mAudioStr = "非常抱歉,没有搜索到您指定的频道.";
cout << rc.mAudioStr << endl;
}
int main(int argc, const char * argv[]) {
// 互为友元类
TV tv;
RemoteController remoteController;
remoteController.setState(tv);
remoteController.setProgramIndex(tv, 12);
cout << "开关机状态:" << ((tv.getState())?"开机":"关机") << endl;
cout << "频道:" << tv.getProgramIndex() << endl;
tv.reply(remoteController);
return 0;
}
4.共同的友元函数
#include <iostream>
using namespace std;
class MyClass2;
class MyClass1
{
private:
string mName;
friend void process(MyClass1 &c1, MyClass2 &c2); // 只是引用了MyClass2,所以在在前面声明就好
};
class MyClass2
{
private:
int mCode;
friend void process(MyClass1 &c1, MyClass2 &c2);
};
void process(MyClass1 &c1, MyClass2 &c2)
{
c1.mName = "Bill Gates";
c2.mCode = 200;
cout << "c1.mName = " << c1.mName << " c2.mCode = " << c2.mCode << endl;
}
int main(int argc, const char * argv[]) {
// 共同的友元函数
MyClass1 c1;
MyClass2 c2;
process(c1, c2); // Bill Gates 200
return 0;
}
5.嵌套类基础
#include <iostream>
using namespace std;
class MyClass
{
public:
class InnerClass
{
private:
int mCode = 100;
public:
int getCode();
void setCode(int code)
{
mCode = code;
}
};
InnerClass* getInnerClass() // 将内嵌类作为返回值
{
return new InnerClass();
}
};
int MyClass::InnerClass::getCode() // 内嵌类的方法在外部的定义/实现
{
return mCode;
}
int main(int argc, const char * argv[]) {
// 内嵌类
MyClass::InnerClass innerClass; // 内嵌类的生成
innerClass.setCode(200);
cout << innerClass.getCode() << endl; // 200
MyClass myClass;
cout << myClass.getInnerClass()->getCode() << endl; // 100
return 0;
}
6.嵌套类的访问权限
private:只有宿主类知道嵌套类的存在,嵌套类对于外部(包括宿主类的外部和宿主类的派生类)是隐藏的
protected:只有宿主类知道嵌套类的存在,嵌套类对于外部(包括宿主类的外部和宿主类的派生类)是隐藏的
public:访问权限没有限制
#include <iostream>
using namespace std;
class MyClass
{
private: // 不能被子类继承
class InnerClass1
{
public:
int code = 50;
};
protected: // 可以被子类继承,但只能是引用形式
class InnerClass2
{
public:
int code = 100;
};
public:
class InnerClass3
{
public:
int code = 200;
};
InnerClass1* getInnerClass1()
{
return new InnerClass1();
}
};
class SubClass : public MyClass
{
public:
InnerClass2* getInnerClass2()
{
return new InnerClass2();
}
InnerClass3* getInnerClass3()
{
return new InnerClass3();
}
};
int main(int argc, const char * argv[]) {
MyClass myClass;
/* MyClass::InnerClass1 *innerClass1 = myClass.getInnerClass1();
会报错,myClass.getInnerClass1()的返回值不能赋值给变量,像下句那样直接
对返回的内容操作是可以的*/
cout << myClass.getInnerClass1()->code << endl; // 50
SubClass subClass;
cout << subClass.getInnerClass2()->code << endl; // 100
SubClass::InnerClass3 *innerClass3 = subClass.getInnerClass3();
cout << innerClass3->code << endl; // 200
return 0;
}
7.模板类中的嵌套类
#include <iostream>
using namespace std;
template <class T>
class Queue
{
private:
class Item
{
public:
T value;
Item* next;
// 构造方法,同时初始化value为传入参数v,初始化指针next为nullptr
Item(const T& v):value(v),next(nullptr)
{
}
};
Item* mFirstItem; // 队列的第一个元素的指针,指向一个类
Item* mLastItem; // 队列的最后一个元素的指针,指向一个类
public:
void enqueue(const T &value); // 入队,函数声明
bool dequeue(T &value); // 出队,函数声明
T* getQueueTop()
{
if(mFirstItem != nullptr)
{
return &mFirstItem->value; //理解为&(mFirstItem->value),返回的是值的地址,不是值本身
}
else
{
return nullptr;
}
}
Queue():mFirstItem(nullptr), mLastItem(nullptr)
{
}
};
template <class T>
void Queue<T>::enqueue(const T& value) // 模板类的方法
{
Item *item = new Item(value);
if(mFirstItem == nullptr)
{
mFirstItem = item;
mLastItem = item;
}
else
{
mLastItem->next = item;
mLastItem = item; // 将新入队的值,插到队列尾部
}
}
template <class T>
bool Queue<T>::dequeue(T &value) // 出队,是出队列头部,方法将出队的值赋给传入的value
{
if(mFirstItem == nullptr)
{
return false;
}
value = mFirstItem->value;
Item *tempItem = mFirstItem;
mFirstItem = mFirstItem->next;
delete tempItem; // 删除出队节点
return true;
}
int main(int argc, const char * argv[]) {
// 模板类中的嵌套类
Queue<string> strQueue;
strQueue.enqueue("xyz");
strQueue.enqueue("龙腾虎跃");
cout << *strQueue.getQueueTop() << endl; // xyz
string value;
strQueue.dequeue(value);
cout << *strQueue.getQueueTop() << endl; // 龙腾虎跃
cout << value << endl; // xyz
return 0;
}