Learn C++学习笔记:第十一章—继承
继承简介C++继承语法非常简单,在class声明之后,我们使用冒号,单词“ public”以及我们希望继承的类的名称。这称为公共继承。#include <iostream>class Base{public:int m_id;Base(int id=0): m_id(id){std::cout <...
继承简介
C++继承语法非常简单,在class声明之后,我们使用冒号,单词public
以及我们希望继承的类的名称。这称为公共继承。
#include <iostream>
class Base
{
public:
int m_id;
Base(int id=0)
: m_id(id)
{
std::cout << "Base\n";
}
int getId() const { return m_id; }
};
class Derived: public Base
{
public:
double m_cost;
Derived(double cost=0.0)
: m_cost(cost)
{
std::cout << "Derived\n";
}
double getCost() const { return m_cost; }
};
子类会继承父类的所有属性和方法。比如上面示例中Derived
也具备id
属性。
11.0 构造函数
实例化时候需要初始化里面的参数,初始化参数不需要调用一个专门的函数,C++里面默认了一个跟类同名的函数,可以用来初始化参数。如上面的Base(int id=0)
、Derived(double cost=0.0)
分别是父类和子类的构造函数。
构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。
实例化某个类时候,很显然就是单纯地在内存里分配地址就行了。但是子类在实例化时候呢?父类的创建顺序如何?
事实上,子类实例化之前会先实例化父类。
class A
{
public:
A()
{
std::cout << "A\n";
}
};
class B: public A
{
public:
B()
{
std::cout << "B\n";
}
};
class C: public B
{
public:
C()
{
std::cout << "C\n";
}
};
class D: public C
{
public:
D()
{
std::cout << "D\n";
}
};
实例化D时候,会依次实例化A,B,C。
11.1 子类实例化与构造函数
子类初始化时候,父类初始化时怎么对父类的参数进行赋值初始化呢?
思路:因为子类可以继承父类,所以可以在子类的构造函数里对父类的参数进行赋值。
结论:不可行。因为父类的参数有可能是const
,无法对常数进行赋值。
C++为了解决这个问题,让我们可以显示地调用父类的构造函数。因为父类本来就要调用构造函数,干脆让使用者可以显示调用,这样就解决了父类参数的赋值问题。
class Derived: public Base
{
public:
double m_cost;
Derived(double cost=0.0, int id=0)
: Base{ id }, // Call Base(int) constructor with value id!
m_cost{ cost }
{
}
double getCost() const { return m_cost; }
};
执行顺序:父类的构造函数先执行,子类的构造函数后执行。
如果有>=3层的继承呢?
对于一个子类它只有一个父类,所以子类里只调用它上一级的父类,然后父类在调用它的父类的构造函数。
如下所示:
class A
{
public:
A(int a)
{
std::cout << "A: " << a << '\n';
}
};
class B: public A
{
public:
B(int a, double b)
: A{ a }
{
std::cout << "B: " << b << '\n';
}
};
class C: public B
{
public:
C(int a , double b , char c)
: B{ a, b }
{
std::cout << "C: " << c << '\n';
}
};
int main()
{
C c{ 5, 4.3, 'R' };
return 0;
}
11.2 继承的三种类成员访问说明符:public,private,protected
因为有3种成员访问说明符:公共,私有和受保护。
对应的,子类继承父类也有这三种关系:公共,私有和受保护。
类成员里面的访问说明符含义:
- public:可以被任意访问
- protected:能被子类、friends、类本身函数访问
- private:能被friend、类本身函数访问,不能被子类访问。
class Base
{
public:
int m_public; // can be accessed by anybody
private:
int m_private; // can only be accessed by Base members and friends (but not derived classes)
protected:
int m_protected; // can be accessed by Base members, friends, and derived classes
};
class Derived: public Base
{
public:
Derived()
{
m_public = 1; // allowed: can access public base members from derived class
m_private = 2; // not allowed: can not access private base members from derived class
m_protected = 3; // allowed: can access protected base members from derived class
}
};
int main()
{
Base base;
base.m_public = 1; // allowed: can access public members from outside class
base.m_private = 2; // not allowed: can not access private members from outside class
base.m_protected = 3; // not allowed: can not access protected members from outside class
}
这个例子充分说明了,访问说明符对外部调用和派生类的影响。
11.3关于类继承的三种访问说明符:
类继承的访问说明符不会影响派生类对基类的访问,主要是影响外部对类成员的访问。
public
继承:
这是用的最多的继承,使用该继承,父类里的说明符的作用范围不会被改变。
公共成员保持公开状态,继承的受保护成员保持受保护状态。由于继承的私有成员在基类中是私有的,因此仍然无法访问。
class Base
{
public:
int m_public;
private:
int m_private;
protected:
int m_protected;
};
class Pub: public Base // note: public inheritance
{
// Public inheritance means:
// Public inherited members stay public (so m_public is treated as public)
// Protected inherited members stay protected (so m_protected is treated as protected)
// Private inherited members stay inaccessible (so m_private is inaccessible)
public:
Pub()
{
m_public = 1; // okay: m_public was inherited as public
m_private = 2; // not okay: m_private is inaccessible from derived class
m_protected = 3; // okay: m_protected was inherited as protected
}
};
int main()
{
// Outside access uses the access specifiers of the class being accessed.
Base base;
base.m_public = 1; // okay: m_public is public in Base
base.m_private = 2; // not okay: m_private is private in Base
base.m_protected = 3; // not okay: m_protected is protected in Base
Pub pub;
pub.m_public = 1; // okay: m_public is public in Pub
pub.m_private = 2; // not okay: m_private is inaccessible in Pub
pub.m_protected = 3; // not okay: m_protected is protected in Pub
private
继承
private继承会让基类里的成员全部变成private
,不可访问。
class Base
{
public:
int m_public;
private:
int m_private;
protected:
int m_protected;
};
class Pri: private Base // note: private inheritance
{
// Private inheritance means:
// Public inherited members become private (so m_public is treated as private)
// Protected inherited members become private (so m_protected is treated as private)
// Private inherited members stay inaccessible (so m_private is inaccessible)
public:
Pri()
{
m_public = 1; // okay: m_public is now private in Pri
m_private = 2; // not okay: derived classes can't access private members in the base class
m_protected = 3; // okay: m_protected is now private in Pri
}
};
int main()
{
// Outside access uses the access specifiers of the class being accessed.
// In this case, the access specifiers of base.
Base base;
base.m_public = 1; // okay: m_public is public in Base
base.m_private = 2; // not okay: m_private is private in Base
base.m_protected = 3; // not okay: m_protected is protected in Base
Pri pri;
pri.m_public = 1; // not okay: m_public is now private in Pri
pri.m_private = 2; // not okay: m_private is inaccessible in Pri
pri.m_protected = 3; // not okay: m_protected is now private in Pri
protected
继承
这种用的非常少。
如果没有关键字,默认的是protected 继承
更多推荐
所有评论(0)