☰
C++运算符重载与多继承及二义性详解
2026/10/6 3:09:43 网站建设 项目流程

1.类外运算符重载

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

classPoint {

private:

intx,y;

public:

// 系统C++源码,大量使用此方式 :x(x), y(y)

Point(intx,inty) :x(x), y(y) {}

// set get 函数

voidsetX(intx) {

this->x = x;

}

voidsetY(inty) {

this->y = y;

}

intgetX() {

returnthis->x;

}

intgetY() {

returnthis->y;

}

};

/*类外运算符重载

* 在真实开发过程中,基本上都是写在类的里面的,外部是不能获取内部的私有成员的

* */

Point operator + (Point point1,Point point2){

intx = point1.getX() + point2.getX();

inty = point1.getY() + point2.getY();

Point res(x, y);

returnres;

}

intmain(){

Point pointA(10,20);

Point pointB(10,20);

Point pointC=pointA+pointB;

cout << pointC.getX() <<" , "<< pointC.getY() << endl;

}

日志输出:
20 , 40

两个对象做+法运算就是执行了运算符重载函数

2.类内部运算符号重载

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

classPoint {

private:

intx,y;

public:

Point(){}

// 系统C++源码,大量使用此方式 :x(x), y(y)

Point(intx,inty) :x(x), y(y) {}

// set get 函数

voidsetX(intx) {

this->x = x;

}

voidsetY(inty) {

this->y = y;

}

intgetX() {

returnthis->x;

}

intgetY() {

returnthis->y;

}

/*

* 常量引用:不允许修改,只读模式

* & 性能的提高,如果没有& 运行+ 构建新的副本,会浪费性能

* 如果增加了& 引用是给这块内存空间取一个别名而已

* */

Point operator + (constPoint & point){

intx=this->x+point.x;

inty=this->y+point.y;

returnPoint(x,y);

}

Point operator - (constPoint & point){

intx=this->x-point.x;

inty=this->y-point.y;

returnPoint(x,y);

}

voidoperator ++() {// ++对象

this->x =this->x + 1;

this->y =this->y + 1;

}

voidoperator ++ (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;

}*/

/*多个<< 连着写 */

friendostream & operator << (ostream & _START,Point &point){

_START <<" 开始输出 "<< point.x <<" : "<< point.y <<" 结束了 "<< endl;

return_START;

}

// istream 输入 系统的

friendistream & operator >> (istream & _START, Point & point) {

// 接收用户的输入,把输入的信息

_START >> point.x >> point.y;

return_START;

}

};

intmain(){

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.[] 运算符号重载

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

classArrayClass {

private:

intsize =0 ;// 大小 开发过程中,给size赋默认值,不然可能会出现,无穷大的问题

int* arrayValue;// 数组存放 int 类型的很多值

public:

ArrayClass(){

/*指针类型必须分配空间*/

arrayValue=static_cast<int*>(malloc(sizeof(int*) * 10));

}

voidset(intindex,intvalue) {

arrayValue[index] = value;// []目前不是我的

size+=1;

}

intgetSize() {// size成员的目标:是为了循环可以遍历

returnthis->size;

}

// 运算符重载 [index]

intoperator[](intindex) {

returnthis->arrayValue[index];// 系统的

}

};

// 输出容器的内容

voidprintfArryClass(ArrayClass arrayClass) {

cout << arrayClass.getSize() << endl;

for(inti = 0; i < arrayClass.getSize(); ++i) {

cout << arrayClass[i] << endl;// []是我们自己的 重载符号

}

}

intmain(){

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++继承

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

classPerson {

public:

char*name;

intage;

public:

Person(char*name,intage) : name(name) {

this->age = age;

cout <<"Person 构造函数"<< endl;

}

voidprint() {

cout <<this->name <<" , "<<this->age << endl;

}

};

classStudent :publicPerson {

private:

char* course;

public:

Student(char* name,intage,char* course) : Person(name, age) , course(course) {

cout <<"Student 构造函数"<< endl;

}

voidtest() {

cout << name << endl;

cout << age << endl;

print();

}

};

  • 默认是 隐式代码: : private Person
  • 私有继承:在子类里面是可以访问父类的成员,但是在类的外面不行
  • 必须公开继承,才可以访问父类的成员
  • 先执行父类的构造函数,再执行子类的构造函数

5.多继承

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

classBaseActivity1 {

public:

voidonCreate() {

cout <<"BaseActivity1 onCreate"<< endl;

}

voidonStart() {

cout <<"BaseActivity1 onStart"<< endl;

}

voidshow() {

cout <<"BaseActivity1 show"<< endl;

}

};

classBaseActivity2 {

public:

voidonCreate() {

cout <<"BaseActivity2 onCreate"<< endl;

}

voidonStart() {

cout <<"BaseActivity2 onStart"<< endl;

}

voidshow() {

cout <<"BaseActivity2 show"<< endl;

}

};

// 子类 继承 二个父类

classMainActivity1 :publicBaseActivity1,publicBaseActivity2{

public:

voidonCreate() {

cout <<"MainActivity1 onCreate"<< endl;

}

voidonStart() {

cout <<"MainActivity1 onStart"<< endl;

}

voidshowSonInfo() {

cout <<"MainActivity1 showSonInfo"<< endl;

}

// void show() {

// cout << "MainActivity1 show" << endl;

//}

};

intmain(){

// 这个是优先寻找子类的函数,因为特别明确,没有问题,还没有产生歧义(二义性)

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.通过虚继承来解决二义性问题

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

// 祖父类

classObject{

public:

intnumber;

voidshow() {

cout <<"Object show run..."<< endl;

}

};

// 父类1

classBaseActivity1 :virtualpublicObject {

};

// 父类2

classBaseActivity2 :virtualpublicObject {

};

// 子类

classSon :publicBaseActivity1,publicBaseActivity2 {

};

intmain(){

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方法,放置在另外一个统一空间上,这样子类再访问的时候就不会出现二义性的问题了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询