C++继承
发表于:2024-12-12 | 分类: C++
字数统计: 1.5k | 阅读时长: 7分钟 | 阅读量:

C++继承

image-20241217210238804

C++支持publicprotected,private三种继承

不写默认private继承,一般使用public继承

普通成员变量

  • 父类的public和protected属性原封继承到子类(任意位置访问或类内访问)

  • 父类private成员变量不可访问

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
#include <iostream>
using namespace std;

class Base
{
public:
int a1;

protected:
int b1;

private:
int c1;
};

class Son : public Base
{
public:
Son()
{
a1 = 1;
b1 = 2;
cout << "a1:" << a1 << endl;
cout << "b1:" << b1 << endl;
}

void set(int value);
};

void Son::set(int value)
{
b1 = value;
cout << "b1:" << b1 << endl;
}
int main()
{
Son s;
s.a1 = 1;
s.set(10);
return 0;
}
  • 父类public和protected属性继承给子类,表现为protected(类内访问)
  • 父类private成员变量不可访问
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
#include <iostream>
using namespace std;

class Base
{
public:
int a1;

protected:
int b1;

private:
int c1;
};

class Son : protected Base
{
public:
Son()
{
a1 = 1;
b1 = 2;
cout << "a1:" << a1 << endl;
cout << "b1:" << b1 << endl;
}

void set(int value);
};

void Son::set(int value)
{
b1 = value;
cout << "b1:" << b1 << endl;
}

int main()
{
Son s;
// a1=10; // 错误,此时a表现为protected
s.set(10);
return 0;
}
  • 父类public和protected属性继承给子类,表现为private(类内访问)
  • 父类private成员变量不可访问
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
#include <iostream>
using namespace std;

class Base
{
public:
int a1;

protected:
int b1;

private:
int c1;
};

class Son : private Base
{
public:
Son()
{
a1 = 1;
b1 = 2;
cout << "a1:" << a1 << endl;
cout << "b1:" << b1 << endl;
}

void set(int value);
};

void Son::set(int value)
{
b1 = value;
cout << "b1:" << b1 << endl;
}
int main()
{
Son s;
s.set(10);
return 0;
}

静态成员变量

除了初始化时要通过父类初始化,其余和普通成员变量相同

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
#include <iostream>
using namespace std;

class Base
{
public:
static int a;

protected:
static int b;

private:
static int c;
};

// 只能使用父类初始化(和之前一样,任何权限都行)
int Base::a = 100;
int Base::b = 200;
int Base::c = 300;

class Son : public Base
{
public:
void print()
{
cout << "Access Base::a in Son: " << a << endl; // 继承的 public 成员
cout << "Access Base::b in Son: " << b << endl; // 继承的 protected 成员
// cout << "Access Base::c in Son: " << c << endl; // 错误!无法访问 private 成员
}
};

int main()
{
Son s;
s.print();

// 通过类名访问 Base 类的 public 静态成员
cout << "Access Base::a directly: " << Base::a << endl;
cout << "Access Son::a directly: " << Son::a << endl;

// 无法通过派生类或对象访问 protected 和 private 静态成员
// cout << "Access Base::b directly: " << Base::b << endl; // 错误!b 是 protected
return 0;
}

成员方法

  • 参考普通成员变量和表格
  • 静态成员方法和普通成员方法继承规则一样
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
#include <iostream>
using namespace std;

class Base
{
public:
void show1();

protected:
void show2();

private:
void show3();
};

class Son : public Base
{
public:
void show();
};

void Base::show1()
{
cout << "Base::show1()" << endl;
}

void Base::show2()
{
cout << "Base::show2()" << endl;
}

void Base::show3()
{
cout << "Base::show3()" << endl;
}

void Son::show()
{
show2();
}

int main()
{
Son s;
s.show();
s.show1();
// s.show2();
// s.show3();
return 0;
}

构造函数和析构函数

参考成员方法,继承规则一致

  • 直接父类的无参构造会被子类构造函数默认调用(父类对象销毁也会触发父类析构)
  • 调用顺序:父类构造->子类构造->子类析构->父类析构

原因:子类需要父类的属性和方法,需要父类先构造。后销毁

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
#include <iostream>
using namespace std;

class Base
{
public:
Base()
{
cout << "Base::Constructor called" << endl;
}

~Base()
{
cout << "Base::Destructor called" << endl;
}
};

class Son : public Base
{
public:
Son()
{
cout << "Son::Constructor called" << endl;
}

~Son()
{
cout << "Son::Destructor called" << endl;
}
};

int main()
{
Son s;
return 0;
}

image-20241218115016177

  • 子类不显式调用父类构造则默认调用无参构造
  • 子类构造通过初始化列表来调用父类构造
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
#include <iostream>
using namespace std;

class Base
{
public:
Base() // 无参构造函数
{
cout << "Base::Default Constructor called" << endl;
}

Base(int x) // 有参构造函数
{
cout << "Base::Parameterized Constructor called with x = " << x << endl;
}

~Base()
{
cout << "Base::Destructor called" << endl;
}
};

class Son : public Base
{
public:
Son(int x, int y)
{
// 有参构造也会默认调用父类的无参构造函数
cout << "Son::Parameterized Constructor called with y = " << y << endl;
}

Son(int x, int y, int z) : Base(x) // 需要使用初始化列表来调用父类的有参构造函数
{
cout << "Son::Parameterized Constructor called with y = " << y << endl;
}
~Son()
{
cout << "Son::Destructor called" << endl;
}
};

int main()
{
Son s2(10, 20); // 调用有参构造函数
cout << "------------------------" << endl;
Son s1(10, 20, 30); // 调用有参构造函数
return 0;
}

方法重写

子类和父类有相同的属性和方法,直接调用的是子类的,如果要调研父类的,使用::

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
#include <iostream>
using namespace std;

class Base
{
public:
int a;
void show1();
};

class Son : public Base
{
public:
int a;
void show1();
};

void Base::show1()
{
cout << "Base::show1()" << endl;
}

void Son::show1()
{
cout << "Son::show1()" << endl;
}

int main()
{
Son s;
// 调用派生类的
s.show1();
s.a = 10;
// 调用基类的
s.Base::show1();
s.Base::a = 20;
return 0;
}

总结

继承规则

image-20241217210238804

构造

  • 子类构造默认调用直接父类的无参构造
  • 如果(初始化列表方式)显示调用父类构造,则不会调用父类无参构造
  • 析构执行顺序与构造执行顺序相反
上一篇:
C++多继承
下一篇:
友元函数