菱形继承和C++相关问题

简介: 菱形继承和C++相关问题

菱形继承

菱形继承是因为多继承存在问题而存在的

像这样都是a的话出现二义性,要采用virtual继承,所以菱形继承它也叫虚继承

#include<iostream>
#include<string>
using namespace std;
class A
{
public:
  A(int a) : a(a){}
protected:
  int a = 555;
};
class B : public A
{
public:
  B(int a):A(a){}
};
class C : public A
{
public:
  C(int a): A(a){}
};
class D : public B, public C
{
public:
  D(int a): B(90), C(68) {}
  void print()
  {
    cout << A::a << endl;
    cout << B::a << endl;
    cout << C::a << endl;
  }
};
int main()
{
  D d(10);
  d.print();
  system("pause");
  return 0;
}

如结果所示,存在二义性问题,这a应该都是一个值,采用virtual继承的方式来解决

在B,C的继承方式前加个virtual,这样子类就必须调用爷爷的构造函数


         

#include

#include

using namespace std;

class A

{

public:

A(int a) : a(a){}

protected:

int a = 555;

};

class B : virtual public A

{

public:

B(int a):A(a){}

};

class C : virtual public A

{

public:

C(int a): A(a){}

};

class D : public B, public C

{

public:

D(int a): B(90), C(68),A(a) {}

void print()

{

cout << A::a << endl;

cout << B::a << endl;

cout << C::a << endl;

}

};

int main()

{

D d(10);

d.print();
system("pause");
return 0;

}

如图所示,打印的结果都是10,这样就不存在二义性问题了

继承中的同名问题

就2种

1.数据成员同名

2.函数同名

在对象的访问中:

如果不加以修饰,那么按照就近原则,

如果用类名限定了,那么自然就调用那类中的

用指针访问时候

注意的是:可以用父类的指针,对子类对象进行初始化,但不能用子类的指针对父类初始化

1.如果不加以修饰,那么调用的,取决于指针的类型,如果是父类的指针类型,那么肯定就调用父类的。

#include<iostream>
#include<string>
using namespace std;
class father
{
public:
  father(){}
  father(string name):name(name){}
protected:
   string name;
};
class son : public father
{
public:
  son(){}
  son(string name1, string name2) :father("father")
  {
    this->name = "son";
  }
  void print()
  {
    cout << son :: name << endl;
    cout << father::name << endl;
  }
protected:
  string name;
};
int main()
{
  son m;
  m.print();
  father* p = new son;
  p->print();
  system("pause");
  return 0;
}

如果所示,这里是父类的指针类型,只能调用父类的东西,调用了子类的东西,编译器自然就报错了。

重载加常量情况

主要是: 有个MM类,它的对象为mm

1.mm = mm + 1

2.mm = 1 + mm

运算符重载的使用情况

#include<iostream>
#include<string>
using namespace std;
class MM
{
public:
  MM(int date) : date(date) {}
  MM operator + (int m)
  {
    this->date = this->date + m;
    return *this;
  }
  void print()
  {
    cout << date << endl;
  }
private:
  int date;
};
int main()
{
  MM mm(1);
  mm = mm + 1;  // 采用的函数运算符重载 , 实质是:  mm.成员函数()
  mm = 1 + mm; // 报错的原因是  1.成员函数()  1无法完成这种转化
  mm.print();
  system("pause");
  return 0;
}

解决这一问题的方法:就是要使用友元函数的运算符重载

#include<iostream>
#include<string>
using namespace std;
class MM
{
public:
  MM(int date) : date(date) {}
  /*MM operator + (int m)
  {
    this->date = this->date + m;
    return *this;
  }*/
  friend MM operator + (MM  date1,MM date2)
  {
    return MM(date1.date + date2.date);
  }
  void print()
  {
    cout << date << endl;
  }
private:
  int date;
};
int main()
{
  MM mm(1);
  mm = mm + 1;  // 采用的函数运算符重载 , 实质是:  mm.成员函数()
  mm = 1 + mm; // 报错的原因是  1.成员函数()  1无法完成这种转化
  //使用友元函数重载,来解决这一问题
  mm.print();
  system("pause");
  return 0;
}

委托构造

构造委托也叫做委托构造,它能够允许有一个构造函数调用另外一个构造函数

它只能采用初始化列表

c++中大部分情况,都需要初始化列表,所以建议,最好每次都是用初始化参数列表

#include<iostream>
#include<string>
using namespace std;
class MM
{
public:
  MM(): MM(10, "温柔了岁月") {}  //这就是委托构造,采用初始化列表
  MM(int age , string name) : age(age),name(name){}
private:
  int age;
  string name;
};
int main()
{
  system("pause");
  return  0;
}



相关文章
|
14天前
|
安全 C++
【c++】继承(继承的定义格式、赋值兼容转换、多继承、派生类默认成员函数规则、继承与友元、继承与静态成员)
本文深入探讨了C++中的继承机制,作为面向对象编程(OOP)的核心特性之一。继承通过允许派生类扩展基类的属性和方法,极大促进了代码复用,增强了代码的可维护性和可扩展性。文章详细介绍了继承的基本概念、定义格式、继承方式(public、protected、private)、赋值兼容转换、作用域问题、默认成员函数规则、继承与友元、静态成员、多继承及菱形继承问题,并对比了继承与组合的优缺点。最后总结指出,虽然继承提高了代码灵活性和复用率,但也带来了耦合度高的问题,建议在“has-a”和“is-a”关系同时存在时优先使用组合。
58 6
|
2月前
|
C++ 开发者
C++学习之继承
通过继承,C++可以实现代码重用、扩展类的功能并支持多态性。理解继承的类型、重写与重载、多重继承及其相关问题,对于掌握C++面向对象编程至关重要。希望本文能为您的C++学习和开发提供实用的指导。
68 16
|
2月前
|
编译器 数据安全/隐私保护 C++
【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】
本实验旨在学习类的继承关系、不同继承方式下的访问控制及利用虚基类解决二义性问题。主要内容包括: 1. **类的继承关系基础概念**:介绍继承的定义及声明派生类的语法。 2. **不同继承方式下对基类成员的访问控制**:详细说明`public`、`private`和`protected`继承方式对基类成员的访问权限影响。 3. **利用虚基类解决二义性问题**:解释多继承中可能出现的二义性及其解决方案——虚基类。 实验任务要求从`people`类派生出`student`、`teacher`、`graduate`和`TA`类,添加特定属性并测试这些类的功能。最终通过创建教师和助教实例,验证代码
71 5
|
4月前
|
编译器 C++ 开发者
【C++】继承
C++中的继承是面向对象编程的核心特性之一,允许派生类继承基类的属性和方法,实现代码复用和类的层次结构。继承有三种类型:公有、私有和受保护继承,每种类型决定了派生类如何访问基类成员。此外,继承还涉及构造函数、析构函数、拷贝构造函数和赋值运算符的调用规则,以及解决多继承带来的二义性和数据冗余问题的虚拟继承。在设计类时,应谨慎选择继承和组合,以降低耦合度并提高代码的可维护性。
48 1
【C++】继承
|
5月前
|
C++
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
81 1
|
5月前
|
C++
C++番外篇——虚拟继承解决数据冗余和二义性的原理
C++番外篇——虚拟继承解决数据冗余和二义性的原理
72 1
|
5月前
|
安全 编译器 程序员
C++的忠实粉丝-继承的热情(1)
C++的忠实粉丝-继承的热情(1)
42 0
|
5月前
|
编译器 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
70 0
|
5月前
|
程序员 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-1
C++入门11——详解C++继承(菱形继承与虚拟继承)-1
68 0
|
1月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。

热门文章

最新文章