目录
一、派生类
1、继承
基类(父类)
class Base
{
public:
int a;
int b;
};
子类
class Derived: public Base//公有的方式继承父类
{
//前面有一个设计精良的父类,做一点点修改,满足需求,实现代码复用
public://有了a,b,自己加了一个c
int c;
};
继承自多个父类
class Derived: public Base1, public Base2
{
...
};
2、构造函数
它是在子类里面如何执行
a.申请内存
b.调用派生构造函数(父类构造函数先执行)
基本对象由基本构造函数构造
成员初始化器列表初始化成员
执行派生构造函数的主体
class Derived: public Base
{
public:
int c;
Derived(int c): Base(c - 2, c - 1), c(c)//指定父类构造函数
1.先执行父类构造函数,并指定父类构造函数。
2.如果不指定父类构造函数,以无参的方式调用父类构造函数,看看哪个符合要求,调哪个。
{
...
}
};
3.析构函数
首先调用派生类(子类)的析构函数,然后是基类(父类)的析构函数。
示例
#include <iostream>
using namespace std;
class Base
{
public:
int a;
int b;
Base(int a = 0, int b = 0)
{
this->a = a;
this->b = b;
cout << "Constructor Base::Base(" << a << ", " << b << ")" << endl;
}
~Base()
{
cout << "Destructor Base::~Base()" << endl;
}
int product()
{
return a * b;
}
//输出Base类的运算符重载
friend std::ostream & operator<<(std::ostream & os, const Base & obj)
{
os << "Base: a = " << obj.a << ", b = " << obj.b;
return os;
}
};
class Derived: public Base
{
public:
int c;//增加成员变量c
//不写构造函数的话,子类构造函数什么也不做,会去调父类的构造函数。
Derived(int c): Base(c - 2, c - 1), c(c)// c(c)初识化c
{
this->a += 3; //它可以在初始化后更改
cout << "Constructor Derived::Derived(" << c << ")" << endl;
}
~Derived()
{
cout << "Destructor Derived::~Derived()" << endl;
}
int product()//和父类的成员函数一样,但有不同的定义。
{
return Base::product() * c;//调用父类的成员函数。
}
friend std::ostream & operator<<(std::ostream & os, const Derived & obj)
{
// call the friend function in Base class
os << static_cast<const Base&>(obj) << endl;//强制类型转换。可以把子类强制转换成父类。
os << "Derived: c = " << obj.c;
return os;
}
};
int main()
{
{
Base base(1, 2);//父类对象
cout << base << endl;
}
cout << "----------------------" << endl;
{
Derived derived(5);//子类对象。
cout << derived << endl;//运算符重载。
cout << "Product = " << derived.product() << endl;
}
return 0;
}
base的析构函数被调用。
{
Base base(1, 2);//父类对象
cout << base << endl;
}
base对象是在{}代码块内,花括号一结束,生命周期结束,对象被销毁,调用析构函数
二、访问控制
使用类编程的时候,我们通常把数据保护起来。所以对类里面的成员就有了访问控制。
1.类的成员访问:
a)public:可在任何地方访问(类的外部可以自由访问)
b)private:只能在类内访问。
class Person {
private:
int n; // private member
public:
// this->n is accessible
Person() : n(10) {}
// other.n is accessible//在类的内部是可以访问的。在外面不可以。
Person(const Person& other) : n(other.n) {}
// this->n is accessible
void set(int n) {this->n = n;}
// this->n and other.n are accessible
void set(const Person& other) {this->n = other.n;}
};
如果class里面没有写标注,那他就是私有的。
2. protected
可以在类的内部使用,也可以在子类的里面使用。
class Base
{
protected:
int n;
private:
void foo1(Base& b)
{
n++; // Okay
b.n++; // Okay
}
};
class Derived : public Base
{
void foo2(Base& b, Derived& d)
{
n++; //Okay
this->n++; //Okay
//b.n++; //Error. 在类外不可使用
d.n++; //Okay
}
};
//一个非成员非友元函数
void compare(Base& b, Derived& d)
{
// b.n++; // Error
// d.n++; // Error
}
3.不同的继承方式
a)public继承
基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员
在子类里面在哪里都能用。但是private在子类不可访问。可以通过父类公有函数访问它。
b)protected继承
当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员
,在子类访问没有问题,在子类的外部不可使用。父类的私有成员不可访问。
c)private继承(最苛刻的继承)
当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员
父类的私有成员依然不可访问。