从C开始的CPP学习生活03-继承

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
class CPeople //基类(父类)
{
public:
void Study()
{
std::cout << "Study" << std::endl;
}
};

class CChild : public CPeople //派生类(子类)
{
public:
void GoToSchool()
{
std::cout << "GoToSchool" << std::endl;
}
};

class CMan : public CPeople
{
public:
void GoToWork()
{
std::cout << "GoToWork" << std::endl;
}
};

class COld : public CPeople
{
public:
void GOToPlay()
{
std::cout << "GOToPlay" << std::endl;
}
};

1、继承限定词

父类成员是哪种修饰符,子类成员就是哪种修饰符

我们以下面的CPeople类为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class CPeople
{
public:
void fun1()
{
std::cout << "father public" << std::endl;
}

protected:
void fun2()
{
std::cout << "father protected" << std::endl;
}

private:
void fun3()
{
std::cout << "father private" << std::endl;
}
};

首先,public修饰符:指子类继承父类时使用的: public CPeople中的public

1
2
3
4
class Cxiaoming : public CPeople
{

};

使用public修饰符继承,父类的成员是什么修饰符,子类的成员就是什么修饰符,子类可以使用父类的public成员

然后,protected修饰符,继承之后,父类的public降级称protected,父类中的protected和private不变,子类不可以使用父类的成员

最后,private修饰符,继承之后,父类成员的所有成员和变量变为private,子类不可用

注意:

  • 继承是指子类继承父类,不管继承的修饰符是什么,父类中的修饰符不会改变,而是父类中的方法被子类继承之后在子类中相对于父类而发生的改变
  • protected修饰符在子类内部可以使用,但是子类的对象无法直接调用prootected修饰符下面的方法

2、构造函数的继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class CPeople
{
public:
CPeople()
{
std::cout << "CPeople" << std::endl;
}
};

class Cxiaoming : public CPeople
{
public:
Cxiaoming()
{
std::cout << "Cxiaoming" << std::endl;
}
};

int main()
{
Cxiaoming xiaoming;
return 0;
}

这段代码执行之后,首先打印CPeople,然后打印Cxiaoming

构造函数的继承,首先调用父类的构造函数,然后调用子类的构造函数

3、有参构造函数的继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class CFather
{
public:
CFather(int a)
{
std::cout << "father class" << std::endl;
}
};

class CSon : public CFather
{
public:
CSon() : CFather(1)
{

}
};

前面提到过,创建子类的对象之前需要先调用父类的构造函数

父类的构造函数如果有参数,则需要子类在构造函数的初始化列表中对父类进行初始化

4、析构函数的继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class CFather
{
public:
~CFather()
{
std::cout << "father class" << std::endl;
}
};

class CSon : public CFather
{
public:
~CSon()
{
std::cout << "CSon class" << std::endl;
}
};

析构函数的调用过程是先调用子类的析构函数,然后调用父类的析构函数

一个对象的声明周期过程中,构造函数与析构函数调用过程为:

父类构造函数 -> 子类构造函数 ->子类析构函数 -> 父类析构函数

5、覆盖

当父类和子类中出现同名的成员时,C++采用覆盖的处理方式

5.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
class CFather
{
public:
int a;
CFather()
{
a = 12;
}
};

class CSon : public CFather
{
public:
int a;
CSon()
{
a = 10;
}

void fun()
{
std::cout << CFather::a << " "<< a << std::endl;
}
};

类外

1
2
3
CSon so;
so.a;
so.CFather::a;

5.2、父类子类函数名相同

子类覆盖父类,使用时可以通过类名作用域区分

父类子类的函数没有重载关系

友元不能被继承


从C开始的CPP学习生活03-继承
http://example.com/2022/10/26/cppnote03/
作者
Anhongzhan
发布于
2022年10月26日
许可协议