C++学习笔记 —— 继承

继承的方式

在这里插入图片描述
首先继承肯定拿不到父类中的private成员,只能拿public和protected
继承的三种方式:

  1. 公有继承,那么子类拿到的父类public和protected还放到自己的public和protected。
  2. 保护继承,子类拿到父类的都放到自己的protected。
  3. 私有继承,子类拿到父类的都放到自己的private。
#include <iostream>

using namespace std;

class Father
{
public:
	int a;

protected:
	int b;

private:
	int c;
};
class Son : public Father
{
public:
	void func()
	{
		cout << a << endl; // father中public但是是用protected方式继承来的。
		cout << b << endl;
		//cout << c << endl; 继承不到
	}
};

int main()
{
	Son son;
	//son.a; 访问不了,因为在子类中是protected的。
}

一般继承都是public继承。protected和private实际中使用很少。

继承中构造和析构顺序

#include <iostream>

using namespace std;

class Father
{
public:
	Father()
	{
		cout << "父类构造" << endl;
	}

	~Father()
	{
		cout << "父类析构" << endl;
	}
};
class Son : protected Father
{
public:
	Son()
	{
		cout << "子类构造" << endl;
	}
	~Son()
	{
		cout << "子类析构" << endl;
	}
};

int main()
{
	Son son;
	
}
/*
父类构造
子类构造
子类析构
父类析构
*/

当父类中没有无参构造

#include <iostream>

using namespace std;

class Father
{
public:

	Father(int a)
	{
		cout << "父类构造" << endl;
	}

	~Father()
	{
		cout << "父类析构" << endl;
	}
};
class Son : public Father
{
public:
	//子类要先调用父类无参构造。但是父类没有无参构造,这时子类会报错
	//解决方法:显示调用父类自定义的有参构造。
	Son(int b): Father(b) //子类这个数直接也传给父类进行初始化
	{
		cout << "子类构造" << endl;
	}
	~Son()
	{
		cout << "子类析构" << endl;
	}
};

int main()
{
	Son son(5);
	
}
/*
父类构造
子类构造
子类析构
父类析构
*/

多继承

#include <iostream>

using namespace std;

class Father1
{
public:
	int a;
};
class Father2
{
public:
	int b;
};
class Son : public Father1, public Father2
{
public:
	int c;
};

int main()
{
	Son son;
	son.a = 9;
	son.b = 10;

}

多继承容易引发二义性的问题。比如两个父类定义了相同的变量.
解决方法:显示定义变量

#include <iostream>

using namespace std;

class Father1
{
public:
	int a;
};
class Father2
{
public:
	int a;
};
class Son : public Father1, public Father2
{
public:
	int c;
};

int main()
{
	Son son;
	son.Father1::a = 9;
	son.Father2::a = 10;
}

但是在实际使用中不建议使用多继承,因为容易引发二义性问题。

虚继承

C++虚继承作用
菱形继承问题。

    class base
    class derived1 :  public base
    class derived2 :  public base
    class derived3 : public derived1, public derived2

这个结构中,当base类中有一个成员变量,而derived3要使用这个变量时就会出现二义性问题。代码如下:

#include <iostream>

using namespace std;

class Parent

{
public:
	int p; // p将会被所有的子类继承,也将是二义性的根源
	Parent()
	{
		p = 10;
	}
};

class Child1 : public Parent
{
public:
	int c1;
	Child1()
	{
		p = 1; // p在子类Child1中被赋值为12
		c1 = 11;
	}
};

class Child2 : public Parent

{
public:
	int c2;
	Child2()
	{
		p = 2; // p在子类Child2中被赋值为13
		c2 = 22;
	}
};

class GrandChild : public Child1, public Child2
{
public:
	int grandchild;
	// p显然也存在于GrandChild中,但是到底是1,还是2呢?这就产生了二义性
	GrandChild()
	{
		grandchild = 3;
	}
};
int main(void)
{
	GrandChild *pGC = new GrandChild();
	cout << pGC->p << endl;// 报错,出现二义性问题
	return 0;
}

解决方法:

#include <iostream>

using namespace std;

class Parent

{
public:
	int p; // p将会被所有的子类继承,也将是二义性的根源
	Parent()
	{
		p = 10;
	}
};
//利用虚继承,则child1为虚基类
class Child1 : virtual public Parent
{
public:
	int c1;
	Child1()
	{
		p = 1; // p在子类Child1中被赋值为12
		c1 = 11;
	}
};

class Child2 : virtual public Parent

{
public:
	int c2;
	Child2()
	{
		p = 2; // p在子类Child2中被赋值为13
		c2 = 22;
	}
};

// 继承了两个虚基类
class GrandChild : public Child1, public Child2
{
public:
	int grandchild;
	// p显然也存在于GrandChild中,但是到底是1,还是2呢?这就产生了二义性
	GrandChild()
	{
		grandchild = 3;
	}
};
int main(void)
{
	GrandChild *pGC = new GrandChild();
	cout << pGC->p << endl;//2 这时用的变量p是多继承中最后继承一个的值也就是child2中的

	return 0;
}
发布了103 篇原创文章 · 获赞 94 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/chongbin007/article/details/104401864