实现基类方法以访问派生类的属性
Posted
技术标签:
【中文标题】实现基类方法以访问派生类的属性【英文标题】:implement a base class method to access a property of derived classes 【发布时间】:2013-08-30 06:33:59 【问题描述】:我有一个基类和几个可以有多个实例的派生类。 派生类有一个静态字符串,其中存储了国籍名称。 看起来像这样……
// Base Class
class Person
private:
// Informations that every person has. Not depending on the nationality
unsigned char m_size;
char[] m_name;
public:
// Get the human readable name of a nationality
void getNationalityName(char* pNatiName);
void Base::getNationalityName(char* pNatiName);
strcpy(pNatiName, m_nationalityName);
// A derived class
class American : public Person
private:
unsigned int m_dollar;
static char[] m_nationalityName;
// Another derived class
class Russian : public Person
private:
unsigned int m_rubel;
static char[] m_nationalityName;
我现在想使用派生类之一的“getNationalityName”方法访问国籍名称。 问题是,基类不知道派生类有一个名为“m_nationalityName”的属性。
我可以在每个类中实现“getNationalityName”方法,但我认为这不是解决这个问题的正确方法。
【问题讨论】:
【参考方案1】:不要。设计看起来有缺陷。国籍应该是一个人的财产(即数据成员)。如果有人有2个国籍怎么办?
enum Nationality
ROMANIAN,
AMERICAN,
RUSSIAN,
;
class Person
Nationality nationality; // or std::vector<Nationality> nationalities;
;
枚举值之后可以很容易地转换。
【讨论】:
我认为 OP 想要一个字符串表示来打印出来,或者类似的东西...... @SingerOfTheFall 随后的转换是微不足道的。我的主要观点是没有那个类层次结构。 是的,这是真的。这也只是我的一个例子,没有人可以有两个国籍,很抱歉造成混淆:)【参考方案2】:使用多态性。使您的getNationalityName
函数virtual
,并在派生类中重新定义它以返回所需的字符串。每次都会调用派生类的函数,返回对应类的字符串:
//base class:
class Person
<...>
public:
virtual void getNationalityName(char* pNatiName);
<...>
// A derived class
class American : public Person
public:
void getNationalityName(char* pNatiName)
strcpy(pNatiName, m_nationalityName);
private:
unsigned int m_dollar;
static char[] m_nationalityName;
<...>
int main()
Person * p = new American();
p->getNationalityName(<...>); // calls American::getNationalityName name even though p is a pointer to the base class.
【讨论】:
似乎是一个不错的解决方案。谢谢你:)【参考方案3】:听起来像m_nationalityName
应该放在你的基类person
中。对我来说,国籍更像是person
的一个属性。只是不要让它static
,因为你不想让所有的人都拥有相同的国籍。
【讨论】:
是的,我也想过这个...但是所有的人都会有相同的国籍,不是吗?还是每个派生类都会有一个新的静态属性实例? 我认为每个民族都应该是一个类,因为每个民族都会有其他不同的属性和方法 好的。如果这是真的,您可以做的一件事是为国籍创建一个新类,并使用组合模式,即让国籍成为您的 Person 类的成员。【参考方案4】:我认为这种情况可以这样处理。因为不同国籍只是名称不同,行为不同,所以不需要使用多态性
class Nationality
private:
Nationality(const char* name_i):m_name(name_i)
const char * m_name;
public:
static Nationality& American()
static Nationality country("American");
return country;
static Nationality& Russian()
static Nationality country("Russia");
void getName(char* pNatiName) const
strcpy(pNatiName, m_name);
;
class Person
private:
<................>
Nationality* nationality
public:
void getNationalityName(char* pNatiName)const
nationality->getName(pNatiName);
;
【讨论】:
【参考方案5】:使用Curiously recurring template pattern,您可以这样做:
template<class T>
class Person
static const std::string m_nationalityName;
// ...
;
template<class T> const std::string Person<T>::m_nationalityName = "Unknown";
class American : public Person<American>
// ...
;
template<> const std::string Person<American>::m_nationalityName = "American";
class Russian : public Person<Russian>
// ...
;
template<> const std::string Person<Russian>::m_nationalityName = "Russian";
不适用于char[]
。
【讨论】:
-1 一方面,它不是解决给定问题的好方法,因为美国人不再是人。其次,它完全适用于 char[] 我尝试使用char[]
,它无法编译,因为字符串的长度不同。我不明白美国人怎么不再是人了。
美国人不是人,而是人。您不再拥有多态 Person 基类。
嗯,你当然可以将它拆分成一个多态的Person
和一个模板化的PersonWithNationality
,或者使用一个traits 结构。我只是想演示如何为每个派生类定义具有不同值的静态类字段。以上是关于实现基类方法以访问派生类的属性的主要内容,如果未能解决你的问题,请参考以下文章