C++运算符重载与多继承及二义性详解
lpf_wei 人气:01.类外运算符重载
class Point { private: int x,y; public: // 系统C++源码,大量使用此方式 :x(x), y(y) Point(int x, int y) :x(x), y(y) {} // set get 函数 void setX(int x) { this->x = x; } void setY(int y) { this->y = y; } int getX() { return this->x; } int getY() { return this->y; } }; /*类外运算符重载 * 在真实开发过程中,基本上都是写在类的里面的,外部是不能获取内部的私有成员的 * */ Point operator + (Point point1,Point point2){ int x = point1.getX() + point2.getX(); int y = point1.getY() + point2.getY(); Point res(x, y); return res; } int main(){ Point pointA(10,20); Point pointB(10,20); Point pointC=pointA+pointB; cout << pointC.getX() << " , " << pointC.getY() << endl; }
日志输出:
20 , 40
两个对象做+法运算就是执行了运算符重载函数
2.类内部运算符号重载
class Point { private: int x,y; public: Point(){} // 系统C++源码,大量使用此方式 :x(x), y(y) Point(int x, int y) :x(x), y(y) {} // set get 函数 void setX(int x) { this->x = x; } void setY(int y) { this->y = y; } int getX() { return this->x; } int getY() { return this->y; } /* * 常量引用:不允许修改,只读模式 * & 性能的提高,如果没有& 运行+ 构建新的副本,会浪费性能 * 如果增加了& 引用是给这块内存空间取一个别名而已 * */ Point operator + (const Point & point){ int x=this->x+point.x; int y=this->y+point.y; return Point(x,y); } Point operator - (const Point & point){ int x=this->x-point.x; int y=this->y-point.y; return Point(x,y); } void operator ++() { // ++对象 this->x = this->x + 1; this->y = this->y + 1; } void operator ++ (int) { // 对象++ this->x = this->x + 1; this->y = this->y + 1; } /*重载<< 输出运算符号 * istream 输入 系统的 * ostream 输出 系统的 * */ /* friend void operator << (ostream & _START,Point &point){ _START << " 开始输出 " << point.x << " : " << point.y << " 结束了 " << endl; }*/ /*多个<< 连着写 */ friend ostream & operator << (ostream & _START,Point &point){ _START << " 开始输出 " << point.x << " : " << point.y << " 结束了 " << endl; return _START; } // istream 输入 系统的 friend istream & operator >> (istream & _START, Point & point) { // 接收用户的输入,把输入的信息 _START >> point.x >> point.y; return _START; } }; int main(){ Point pointA(30,50); Point pointB(10,20); // Point pointC=pointA-pointB; ++pointA; // cout << pointA.getX() << " , " << pointA.getY() << endl; cout << pointA << pointB <<endl; // 多个的 Point pointC; cin >> pointC; // >> 是我们自己重载的哦 cout << "你输入的是:" << pointC.getX() << endl; cout << "你输入的是:" << pointC.getY() << endl; }
- 类内部运算符重载,允许访问私有变量
- 传入的参数是常量引用,const 表示不可更改,& 可以提升性能,只会有一个变量别名,不加会拷贝一份,浪费内存。
- << >> 重载,需要加friend 友元函数来进行重载
- ostream & _START:表示输出
- istream & _START:表示输入
3.[] 运算符号重载
class ArrayClass { private: int size =0 ; // 大小 开发过程中,给size赋默认值,不然可能会出现,无穷大的问题 int * arrayValue; // 数组存放 int 类型的很多值 public: ArrayClass(){ /*指针类型必须分配空间*/ arrayValue= static_cast<int *>(malloc(sizeof(int *) * 10)); } void set(int index, int value) { arrayValue[index] = value; // []目前不是我的 size+=1; } int getSize() { // size成员的目标:是为了循环可以遍历 return this->size; } // 运算符重载 [index] int operator[](int index) { return this->arrayValue[index]; // 系统的 } }; // 输出容器的内容 void printfArryClass(ArrayClass arrayClass) { cout << arrayClass.getSize() << endl; for (int i = 0; i < arrayClass.getSize(); ++i) { cout << arrayClass[i] << endl; // []是我们自己的 重载符号 } } int main(){ ArrayClass arrayClass; // 栈区 实例出来的对象,是在堆区了 arrayClass.set(0, 100); arrayClass.set(1, 200); arrayClass.set(2, 300); arrayClass.set(3, 400); arrayClass.set(4, 500); printfArryClass(arrayClass); }
4.c++继承
class Person { public: char *name; int age; public: Person(char *name, int age) : name(name) { this->age = age; cout << "Person 构造函数" << endl; } void print() { cout << this->name << " , " << this->age << endl; } }; class Student : public Person { private: char * course; public: Student(char * name, int age, char* course) : Person(name, age) , course(course) { cout << "Student 构造函数" << endl; } void test() { cout << name << endl; cout << age << endl; print(); } };
- 默认是 隐式代码: : private Person
- 私有继承:在子类里面是可以访问父类的成员,但是在类的外面不行
- 必须公开继承,才可以访问父类的成员
- 先执行父类的构造函数,再执行子类的构造函数
5.多继承
class BaseActivity1 { public: void onCreate() { cout << "BaseActivity1 onCreate" << endl; } void onStart() { cout << "BaseActivity1 onStart" << endl; } void show() { cout << "BaseActivity1 show" << endl; } }; class BaseActivity2 { public: void onCreate() { cout << "BaseActivity2 onCreate" << endl; } void onStart() { cout << "BaseActivity2 onStart" << endl; } void show() { cout << "BaseActivity2 show" << endl; } }; // 子类 继承 二个父类 class MainActivity1 : public BaseActivity1, public BaseActivity2{ public: void onCreate() { cout << "MainActivity1 onCreate" << endl; } void onStart() { cout << "MainActivity1 onStart" << endl; } void showSonInfo() { cout << "MainActivity1 showSonInfo" << endl; } // void show() { // cout << "MainActivity1 show" << endl; //} }; int main(){ // 这个是优先寻找子类的函数,因为特别明确,没有问题,还没有产生歧义(二义性) MainActivity1 mainActivity1; // 子类 mainActivity1.onCreate(); mainActivity1.onStart(); mainActivity1.showSonInfo(); // 不明确,二义性,歧义 /*request for member ‘show' is ambiguous*/ // mainActivity1.show(); /*解决二义性 通过.来引出父类 然后再调用*/ mainActivity1.BaseActivity3::show(); mainActivity1.BaseActivity2::show(); mainActivity1.BaseActivity1::show(); // 解决方案二: 子类上 重写父类的show函数 mainActivity1.show(); }
- c++ 允许多继承,可能会出现二义性,原则上是尽量避免二义性
- 通过明确父类的方式解决二义性
- 通过子类重写父类的方法规避二义性
6.通过虚继承来解决二义性问题
// 祖父类 class Object{ public: int number; void show() { cout << "Object show run..." << endl; } }; // 父类1 class BaseActivity1 : virtual public Object { }; // 父类2 class BaseActivity2 : virtual public Object { }; // 子类 class Son : public BaseActivity1, public BaseActivity2 { }; int main(){ Object object; BaseActivity1 baseActivity1; BaseActivity2 baseActivity2; Son son; object.number = 100; baseActivity1.number = 200; baseActivity2.number = 300; son.number = 400; object.show(); baseActivity1.show(); baseActivity2.show(); son.show(); cout << object.number << endl; cout << baseActivity1.number << endl; cout << baseActivity2.number << endl; cout << son.number << endl; }
- 如果没有虚继承,那么son对象访问number就会报二义性的问题,同时访问show方法同样存在二义性问题
- 由于在继承的时候添加了虚继承,就能解决类似这样的问题,虚继承的含义是:将通过继承得来的number和show方法,放置在另外一个统一空间上,这样子类再访问的时候就不会出现二义性的问题了。
加载全部内容