c++防止继承基类的特定公共成员
C++ prevent inherit specific public member of base class
如何防止公共成员被它的派生类继承?比如,如果我有这个:
class Person {
public:
enum { MALE, FEMALE, BOTH };
Person(std::string name, int gender)
: _name(name)
{
switch (gender) { /* processing here */ }
}
protected:
std::string _name;
};
class Male : public Person {
public:
Male(std::string name)
: _name(name, 0) { }
};
我想这样做的原因是,我希望能够实例化一个person类,如:
Person person("The Name", Person::MALE);
但是,由于enum
是公共的,这也是可用的:
Male::MALE
Male::FEMALE
Male::BOTH
已经没有意义了。如何防止派生类能够访问这些枚举值,但使其可从基类的公共?
如果您坚持将enum
保留在基类中,则可以将enum
放置在受保护的部分中。
class Person {
protected:
enum Gender { MALE, FEMALE, BOTH };
Person(std::string name, Gender gender)
: _name(name)
{
switch (gender) { /* processing here */ }
}
std::string _name;
public:
virtual ~Person () {}
//...
};
从Person
公开派生的类仍然可以访问enum
的值,但是派生类的用户不能。
class Male : public Person {
public:
Male (std::string name) : Person(name, MALE) {}
//...
};
因此,Male
可以使用MALE
,但Male
的用户将无法看到Male::MALE
, Male::FEMALE
和Male::BOTH
,这是您最初的问题之一。至于您的问题,您并不是真的想要拒绝派生类访问,因为您希望派生类能够指定Gender
。并且不应该允许任何直接用户使用Person
。相反,Person
的用户选择一个正确的派生类,这将正确地建立Gender
。
class Female : public Person {
public:
Female (std::string name) : Person(name, FEMALE) {}
//...
};
class Transgender : public Person {
public:
Transgender (std::string name) : Person(name, BOTH) {}
//...
};
std::shared_ptr<Person> p = std::make_shared<Female>("Beth");
OP中的评论建议重新考虑您的设计,这可能是最好的选择。
但是,如果您想跟上您在答案中所写的内容,一种可能性是从基类
派生protected
ly。class Person {
public:
enum { MALE, FEMALE, BOTH };
Person(std::string name, int gender)
: _name(name)
{
switch (gender) { /* processing here */ }
}
protected:
std::string _name;
};
class Male : protected Person
{ //^^^^^^^^^
public:
Male(std::string name)
: Person(name, 0) { }
void foo() { FEMALE; } // still ok, a public field derived protected'ly is accessible
};
int main()
{
Male male("Joe");
male.MALE; //error, cannot call the enum from outside the class
}
问题似乎是文字问题,代码本身没有问题,而是将代码视为反映公共概念的语言。
在这个意义上,我建议以下答案:
有一个工厂(或工厂方法),其中枚举仅在该工厂中是公共的。换句话说,创建一个新的工厂Human
,并使用Human
枚举拥有所有基类和派生类。然后基类仍然可以是Person
,但Person
没有任何enum MALE
/FEMALE
/等。只有Human
工厂这样做,并且它不是子类化的基类。这将导致代码可以像这样字面理解:
Person person("The Name", Human::MALE);
您也可以像这样使用Gender
工厂(而不是Human
)(更有文化并分离相互依赖):
Person person("The Name", Gender::MALE);
注意,基类包含所有派生类必须共享的最小公分母。因此,由于衍生类Male
Female
等不应该共享gender enum
,那么它不应该是基类的一部分,而是一个类或构造本身,然后由Person
类及其衍生物使用。
使用受保护的构造函数使Person
类抽象:
class Person {
public:
enum Gender {
MALE,
FEMALE,
BOTH
};
protected:
// Protected constructor can only be called from subclasses.
Person(std::string name, Gender gender)
: _name(name)
{
switch (gender) { /* processing here */ }
}
protected:
std::string _name;
};
class Male : public Person {
public:
Male(std::string name)
: Person(name, MALE)
{
}
};
如果性别独立于Person类,只需将其移出类:
enum Gender {
GenderMale,
GenderFemale,
GenderBoth
};
class Person //...
class Male // ...
还可以将Gender封装到自己的类中:
class Gender {
public:
enum Type { Male, Female, Both };
Gender(Type type);
Gender(const Gender ©);
Gender& operator=(Gender &assign);
public:
bool operator==(const Gender &other) const;
// etc.
public:
std::string toString() const;
};
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 如何从另一个文件继承私有成员变量和公共函数
- C++继承更改成员
- 继承和友元函数,从基类访问受保护的成员
- 删除C++继承中虚拟类成员的代码重复
- 成员包含其他继承类的继承类?
- 如何定义一个没有重复代码的继承的 const 类成员函数?
- 打印所有继承的类成员变量和方法
- 如何在复杂继承中访问静态成员变量
- enable_if继承的成员函数的名称查找错误
- 初始化依赖于子类的继承类的常量类成员
- 继承:调用基类的成员和方法
- 类设计:类成员继承自同一基类
- 使用 CRTP 进行选择性静态成员继承
- 具有'using'的模板模板成员继承
- 结构绑定:与公共数据成员(继承的基类)结合
- 为什么C++继承不允许基类的公共成员继承到派生类的私有成员?
- 静态成员继承和保护
- 是否可以检查是否为类定义了成员函数,即使该成员继承自未知基类
- 混合模板/非模板继承分类和成员继承