类的继承——补充知识
● public 与 private 继承(C++ Public, Protected and Private Inheritance)
改变了类所继承的成员的访问权限
//公有继承
struct Base
{
public:
int x;
private:
int y;
protected:
int z;
};
struct Derive : public Base //公有继承基类
{
/*public:
int x;
protected:
int z;*/
void fun()
{
x = 10; //可以访问,公有继承基类后,基类中的公有成员在派生类中的访问权限仍然是公有成员
y = 11; //不可访问,无论哪种继承基类,基类的私有成员只能在基类中访问 Error: 'y' is a private member of 'Base'
z = 12; //可以访问,公有继承基类后,基类中的保护成员在派生类中的访问权限仍然是保护成员
}
};
struct Derive2 : public Derive //公有继承派生类
{
void fun()
{
x = 10; //可以访问,公有继承派生类后,基类中的公有成员在派生类的派生类中的访问权限仍然是公有成员
y = 11; //不可访问,无论哪种继承派生类,基类的私有成员只能在基类中访问 Error: 'y' is a private member of 'Base'
z = 12; //可以访问,公有继承派生类后,基类中的保护成员在派生类的派生类中的访问权限仍然是保护成员
}
};
int main()
{
Base val;
val.x; //类外可以访问该类的公有成员
val.y; //类外不能访问该类的私有成员, Error: 'y' is a private member of 'Base'
val.z; //类外不能访问该类的保护成员, Error: 'z' is a protected member of 'Base'
Derive d;
d.x; //派生类对象可以在类外访问基类的公有成员
d.y; //派生类对象不可在类外访问基类的私有成员,Error: 'y' is a private member of 'Base'
d.z; //派生类对象不可在类外访问基类的保护成员,Error: 'z' is a protected member of 'Base'
Derive2 d2;
d2.x; //派生类的派生类对象可以在类外访问基类的公有成员
d2.y; //派生类的派生类对象不可在类外访问基类的私有成员,Error: 'y' is a private member of 'Base'
d2.z; //派生类的派生类对象不可在类外访问基类的保护成员,Error: 'z' is a protected member of 'Base'
}
//保护继承
struct Base
{
public:
int x;
private:
int y;
protected:
int z;
};
struct Derive : protected Base //保护继承基类
{
/*protected:
int x;
protected:
int z;*/
void fun()
{
x = 10; //可以访问,保护继承基类后,基类中的保护成员在派生类中的访问权限成为保护成员
y = 11; //不可访问,无论哪种继承基类,基类的私有成员只能在基类中访问 Error: 'y' is a private member of 'Base'
z = 12; //可以访问,保护继承基类后,基类中的保护成员在派生类中的访问权限仍然是保护成员
}
};
struct Derive2 : public Derive //公有继承派生类
{
void fun()
{
x = 10; //可以访问,公有继承派生类后,基类中的公有成员在经过派生类的保护继承后变成保护成员,在派生类的派生类中仍是保护成员
y = 11; //不可访问,无论哪种继承派生类,基类的私有成员只能在基类中访问 Error: 'y' is a private member of 'Base'
z = 12; //可以访问,公有继承派生类后,基类中的保护成员在派生类的派生类中的访问权限仍然是保护成员
}
};
int main()
{
Base val;
val.x; //类外可以访问该类的公有成员
val.y; //类外不能访问该类的私有成员, Error: 'y' is a private member of 'Base'
val.z; //类外不能访问该类的保护成员, Error: 'z' is a protected member of 'Base'
Derive d;
d.x; //基类中的公有成员在经过派生类的保护继承后变成派生类的保护成员,派生类对象不可在类外访问自己的保护成员,Error: 'x' is a protected member of 'Base'
d.y; //派生类对象不可在类外访问基类的私有成员,Error: 'y' is a private member of 'Base'
d.z; //保护继承对基类的保护成员的访问权限无影响,派生类对象不可在类外访问基类的保护成员,Error: 'z' is a protected member of 'Base'
Derive2 d2;
d2.x; //基类中的公有成员在经过派生类的保护继承后变成派生类的保护成员,派生类的派生类对象不可在类外访问该保护成员,Error: 'x' is a protected member of 'Base'
d2.y; //派生类的派生类对象不可在类外访问基类的私有成员,Error: 'y' is a private member of 'Base'
d2.z; //保护继承对基类的保护成员的访问权限无影响,派生类的派生类对象不可在类外访问该保护成员,Error: 'z' is a protected member of 'Base'
}
//私有继承
struct Base
{
public:
int x;
private:
int y;
protected:
int z;
};
struct Derive : private Base //私有继承基类
{
/*private:
int x;
private:
int z;*/
void fun()
{
x = 10; //可以访问,私有继承基类后,基类中的保护成员在派生类中的访问权限成为私有成员
y = 11; //不可访问,无论哪种继承基类,基类的私有成员只能在基类中访问 Error: 'y' is a private member of 'Base'
z = 12; //可以访问,私有继承基类后,基类中的保护成员在派生类中的访问权限成为私有成员
}
};
struct Derive2 : public Derive //公有继承派生类
{
void fun()
{
x = 10; //不可访问,公有继承派生类后,基类中的公有成员在经过派生类的私有继承后变成私有成员,在派生类的派生类中已不可见,Error: 'x' is a private member of 'Base'
y = 11; //不可访问,无论哪种继承派生类,基类的私有成员只能在基类中访问,Error: 'y' is a private member of 'Base'
z = 12; //不可访问,公有继承派生类后,基类中的保护成员在经过派生类的私有继承后变成私有成员,在派生类的派生类中已不可见,Error: 'z' is a private member of 'Base'
}
};
int main()
{
Base val;
val.x; //类外可以访问该类的公有成员
val.y; //类外不能访问该类的私有成员, Error: 'y' is a private member of 'Base'
val.z; //类外不能访问该类的保护成员, Error: 'z' is a protected member of 'Base'
Derive d;
d.x; //基类中的公有成员在经过派生类的私有继承后变成派生类的私有成员,派生类对象不可在类外访问自己的私有成员,Error: 'x' is a private member of 'Base'
d.y; //派生类对象不可在类外访问基类的私有成员,Error: 'y' is a private member of 'Base'
d.z; //基类中的保护成员在经过派生类的私有继承后变成派生类的私有成员,派生类对象不可在类外访问自己的私有成员,Error: 'z' is a private member of 'Base'
Derive2 d2;
d2.x; //基类中的公有成员在经过派生类的保继承后变成派生类的私有成员,派生类的派生类对象不可在类外访问该私有成员,Error: 'x' is a private member of 'Base'
d2.y; //派生类的派生类对象不可在类外访问基类的私有成员,Error: 'y' is a private member of 'Base'
d2.z; //基类中的保护成员在经过派生类的私有继承后变成派生类的私有成员,派生类的派生类对象不可在类外访问该私有成员,Error: 'z' is a private member of 'Base'
}
– public 继承:描述 是一个 的关系 “ ”
– private 继承:描述 根据基类实现出 的关系 “ ”
– protected 继承:几乎不会使用
● using 与继承
– 使用 using 改变基类成员的访问权限
● 派生类可以访问该成员
struct Base
{
public:
int x = 10;
private:
int y = 20;
protected:
int z = 30;
};
struct Derive : Base
{
public:
using Base::z; //在派生类中使用using改变了基类成员的访问权限,using只能改变在派生类中可见的基类成员的访问权限(即公有成员和保护成员)
using Base::y; //基类的私有成员在基类外都是不可见的,因此不能使用using改变基类私有成员的访问权限, Error: 'y' is a private member of 'Base'
};
int main()
{
Derive d;
std::cout << d.x << '\n'; //Of course OK
std::cout << d.z << '\n'; //OK
}
● 无法改变构造函数的访问权限
struct Base
{
protected:
Base(int) {}
};
struct Derive : Base
{
public:
using Base::Base; //Error: 'Base(int)' is protected within this context
};
struct Base
{
protected:
void fun()
{
std::cout << "void fun()\n";
}
void fun(int input)
{
std::cout << "void fun(int input): " << input << '\n';
}
void fun(char ch)
{
std::cout << "void fun(char ch): " << ch << '\n';
}
};
struct Derive : Base
{
public:
using Base::fun; //同时改变基类中重载的三个fun()的权限
};
int main()
{
Derive d;
d.fun(); //OK
d.fun(3); //OK
d.fun('a'); //OK
}
struct Base
{
protected:
void fun()
{
std::cout << "void Base::fun()\n";
}
void go()
{
std::cout << "void Base::go()\n";
}
};
struct Derive : private Base
{
public:
using Base::fun; //私有继承后,Base::fun()在派生类中成为私有成员,使用using改变其成为公有成员
void go2()
{
std::cout << "void Derive::go2()\n";
go();
}
};
int main()
{
Derive d;
d.fun();
d.go2();
}
– 使用 using 继承基类的构造函数逻辑
struct Base
{
public:
Base(int) //公有成员
{
std::cout << "Base(int)\n";
}
};
struct Derive : Base
{
public:
using Base::Base;
};
int main()
{
Derive d(10);
}
struct Base
{
public:
Base(int)
{
std::cout << "Base(int)\n";
}
};
struct Derive : Base
{
public:
Derive(int x)
: Base(x) //对基类构造函数的增删改会影响到派生类构造函数的增删改,维护极其不便
{}
using Base::Base; //使用using
};
– using 与部分重写
struct Base
{
protected:
virtual void fun()
{
std::cout << "virtual void fun()\n";
}
virtual void fun(int)
{
std::cout << "virtual void fun(int)\n";
}
};
struct Derive : Base
{
public:
using Base::fun;
};
int main()
{
Derive d;
d.fun();
d.fun(100);
}
struct Base
{
protected:
virtual void fun()
{
std::cout << "virtual void Base::fun()\n";
}
virtual void fun(int)
{
std::cout << "virtual void Base::fun(int)\n";
}
};
struct Derive : Base
{
public:
using Base::fun;
void fun(int) override
{
std::cout << "void Derive::fun(int) override\n";
}
};
int main()
{
Derive d;
d.fun();
d.fun(100);
}
struct Base
{
protected:
Base(int) = default; //保护成员,Error: Only special member functions may be defaulted
};
struct Derive : Base
{
public:
using Base::Base;
};
int main()
{
Derive d(10); //Error: Calling a protected constructor of class 'Base'
}
struct Base
{
protected:
Base() = default; //OK,编译器为Base合成了一个缺省构造函数,权限为public,供外界使用
};
struct Derive : Base
{
};
int main()
{
Derive d; //OK
}
● 继承与友元:友元关系无法继承,但基类的友元可以访问派生类中基类的相关成员
//基类的友元
struct Base
{
friend void fun(const Base&); //fun是Base的友元
public:
int x;
private:
int y;
protected:
int z;
};
struct Derive : Base
{
private:
int xxx;
};
void fun(const Base& b)
{
b.x; //OK
b.y; //OK
b.z; //OK
const auto& d = static_cast<const Derive&>(b);
d.xxx; //fun是Base的友元,Derive派生自Base,但fun并不是Derive的友元
}
//派生类的友元
struct Base
{
public:
int x;
private:
int y;
protected:
int z;
};
struct Derive : Base
{
friend void fun(const Derive&); //fun是Derive的友元
private:
int xxx;
};
void fun(const Derive& d)
{
d.x; //fun是Derive的友元,可以访问Derive中所有可见的基类成员
d.y; //不可访问,Error: 'y' is a private member of 'Base',
d.z; //fun是Derive的友元,可以访问Derive中所有可见的基类成员
d.xxx; //fun是Derive的友元,可以访问Derive的所有成员
}
参考
深蓝学院: C++基础与深度解析
C++ Public, Protected and Private Inheritance