C++特殊成员
const成员
- const数据成员
- const类型变量是不可以修改,只读模式
- 必须采用初始化参数列表方式进行初始化
- const成员函数
- 写法上, const写在函数后面
- 常成员函数是不能够修改数据成员,只读数据成员
- 常成员函数可以与普通函数同时存在
- 普通函数和常成员函数相同时,普通对象优先调用普通函数
- 普通对象可以调用常成员函数
- const对象: const修饰的对象
- 常对象只能调用常成员函数
#include <iostream> #include <string> using namespace std; class MM { public: MM(string name, int num) :num(num) { MM::name = name; //可以用,也可以不用初始化列表 //MM::num = 1001; 必须要用初始化参数列表方式初始化 } void print() { //不能修改 //num = 1001; 错误,只读模式 cout << name << " " << num << endl; } //常成员函数 void print()const { //name = "修改"; 错误,常成员函数不能修改数据 //num = 199; cout << "常成员函数" << endl; } void printData() { cout << "普通函数" << endl; } protected: string name; const int num; //const数据成员 }; int main() { MM mm("对象", 18); mm.print(); //普通对象调用普通函数 const MM cmm("常对象", 20); cmm.print(); //常对象调用常成员函数 //cmm.printData(); //错误!,常对象只能调用普通函数 return 0; }
static成员
static成员是不属于对象,是属于类的,意味着是所有对象共有的,调用可以不需要对象,也可以用对象调用。当用对象调用时,static成员依旧受权限限定。
static数据成员
必须在类外初始化,不再需要static修饰,但是需要类名限定
类中初始化是错误的,不能采用初始化参数列表方式初始化
static成员函数
static写在函数前面即可
调用非静态成员 必须要指定对象
static对象
释放是最后释放的
#include <iostream> using namespace std; class MM { public: MM(string name=""):name(name) { num++; } static void printMM(); static void printData(MM& mm) { cout << mm.name <<" "<<num <<endl; } protected: string name; public: static int num; }; //类外初始化,不再需要static修饰,但是需要类名限定 int MM::num = 1; //类外初始化,不再需要static修饰 void MM::printMM() { //调用非静态数据成员,必须要指定对象 //cout << name << endl; 当这个函数不采用对象去调用,name没有来源 //静态调用静态,没什么要求 cout << num << endl; cout << "静态成员函数" << endl; } int main() { //静态数据成员访问,可以不需要对象 cout << MM::num << endl; //什么叫做共有的 MM mm("mm"); //静态数据成员可以通过对象去访问 cout << mm.num << endl; //此时num等于2 MM array[3]; //5 MM* p = new MM("newMM"); //6 cout << MM::num << endl; cout << p->num << endl; cout << mm.num << endl; delete p; p = nullptr; //静态成员函数 MM::printMM(); mm.printMM(); MM::printData(mm); return 0; }
友元
友元用friend描述 ,友元只提供场所,赋予对象具有打破类的权限定(无视权限)
- 友元函数
- 普通友元函数
- 以另一个类的成员函数充当友元函数,顺序如下:
- B 类
- A 类
- A 类的友元函数(B类的成员函数)
- 友元类
#include <iostream> using namespace std; class MM { friend class GG; public: MM(string name, int age) :name(name), age(age) {} protected: string name; int age; }; class GG { public: void print() { MM mm("mm", 18); cout << mm.name << "\t" << mm.age << endl; } void printMM(MM& mm) { cout << mm.name << "\t" << mm.age << endl; } MM& returnMM(MM& mm) { return mm; } protected: }; //互为友元类的写法 class A { friend class B; public: void printData(); protected: string data="A"; }; class B { public: friend class A; void printData() { A a; cout << a.data << endl; } protected: string data = "B"; }; void A::printData() { B b; cout << b.data << endl; } int main() { MM mm("mm", 18); GG gg; gg.print(); gg.printMM(mm); //cout << gg.returnMM(mm).name << endl; 错误,出了友元类,没有权限 //互为友元 B b; b.printData(); A a; a.printData(); return 0; }
this指针与explicit
- explicit修饰构造函数使用,不让隐式转换构造
- this指针
- 避免形参名和数据成员同名,通指对象的地址
- 充当函数返回值,返回对象自身,用*this表示对象本身
- 静态成员函数中是不能使用this指针
#include <iostream> using namespace std; class MM { public: explicit MM(int age) :age(age) {} void print() { cout << age << endl; } protected: int age; }; class GG { public: GG(string name, int age) :name(name), age(age) {} //普通函数不存在初始化参数列表 void initData(string name, int age) { //类名限定 帮助计算机去识别 GG::name = name; this->age = age; } void print() { cout << this->name << " " << this->age << endl; } void printThis() { cout << this << endl; } GG& returnGG() { return *this; } void printGG2(GG& gg) {} static void printStatic() { GG gg("this", 19); cout << gg.name << "\t" << gg.age << endl; } protected: string name; int age; }; int main() { //explicit 不让隐式转换构造 //MM mm = 12; //MM temp = 1.33; MM temp(12); temp.print(); GG gg("长沙吴彦祖", 28); gg.print(); gg.initData("顿开吴彦祖", 38); gg.print(); cout << &gg << endl; gg.printThis(); GG boy("哥哥吴彦祖", 38); cout << &boy << endl; boy.printThis(); gg.returnGG().returnGG().returnGG().returnGG().returnGG().returnGG().print(); GG::printStatic(); return 0; }
小练习
实现string中创建方式:
通过实现data和c_str函数 打印字符串
实现append 实现字符串的链接
实现字符串比较
手写析构函数释放内存
#include <iostream> #include <cstring> using namespace std; class mystring { public: //mystring() //{ // strSize = 1; // str = new char; // *str='\0'; //}; mystring(const char* str="") { strSize = strlen(str) + 1; mystring::str = new char[strSize]; strcpy_s(mystring::str,strSize,str); } mystring(const mystring& object) { strSize = object.strSize; str = new char[strSize]; strcpy_s(str, strSize, object.str); } char* c_str() { return str; } char* data() { return str; } mystring append(const mystring& object) { //"strcat_s()函数"使用时需要考虑内存空间大小问题,所以创建临时变量来设置大小 mystring temp; //由于两个字符串各有一个"\0",所以-1删去一个"\0" temp.strSize = mystring::strSize + object.strSize-1; temp.str = new char[temp.strSize]; memset(temp.str, 0, temp.strSize); strcat_s(temp.str, temp.strSize, str); strcat_s(temp.str, temp.strSize, object.str); return temp; } int compare(const mystring& object) { return strcmp(str, object.str); } ~mystring() { delete[] str; str = nullptr; } protected: char* str; //需要存储 int strSize; }; int main() { { //1.实现string中创建方式 mystring str1; mystring str2("ILoveyou"); mystring str3(str1); mystring str4 = str2; //2.通过实现data和c_str函数 打印字符串 cout << str2.c_str() << endl; //打印ILoveyou cout << str2.data() << endl; //打印ILoveyou //3.实现append 实现字符串的链接 mystring strOne = "one"; mystring strTwo = "two"; mystring strThree = strOne.append(strTwo); cout << strThree.data() << endl; //onetwo //4.实现字符串比较 cout << strOne.compare(strOne) << endl; //0 } //5.手写析构函数释放内存 return 0; }