C ++继承与父“知道”这些孩子 [英] C++ Inheritance with parent "knowing" the children
问题描述
Hello我有一个全局数组,我们说
array = [A,B,C ,D,E]
我想设计一个有5个子类的父类
Parent,Child1,Child2,Child3,Child4,Child5
Parent类将有一个方法名称getID();
如何设计这样的行为
Child1.getID()是数组[0]给出A
Child2.getID [1]给出B
Child3.getID()是数组[2]给出C
Child4.getID()是数组[3]给出D
Child5.getID ()是数组[4]给出E
这是否可能?
原因是我不想为5个孩子保持复制和粘贴getID()。
我想假设目标是在父类中写getID避免在每个子类中重复 getID()
的主体。但我也认为将数组移动到父类是不理想。
有很多选项可以用来避免样板代码。
在父
中只使用一个子类和一个工厂方法。 >将公共代码推入基类,并向父类添加一个工厂方法(如果合适,您甚至可以合并父类和基类)。
struct ChildBase:public Base {
explicit ChildBase(const char * name):name(name){};
const char * name;
const char * getID(){return name; }
}
struct Base {
ChildBase getChild1(){return ChildBase(A); }
ChildBase getChild2(){return ChildBase(B); }
}
或甚至
struct Base {
const char * ids = {A,B,C,...}
ChildBase getChild(int i){return ChildBase(ids [i]); }
}
第二种形式很容易推广到在运行时加载配置。 p>
使用基类
将公共代码推入基类。
通常会是这样:
struct ChildBase:public Base {
ChildBase(const char * name):name(name){};
const char * name;
const char * getID(){return name; }
}
struct Child1:public ChildBase {
Child1():ChildBase(A){};
}
struct Child2:public ChildBase {
Child2():ChildBase(B){};
}
但这不会节省太多,因为你仍然需要自定义构造函数。您可以使用模板化的基类来减少cruft。
template< const char * ID>
structure ChildBase(){
const char * getID(){return ID; }
};
struct Child1:public ChildBase<A>();
struct Child2:public ChildBase<B>();
宏
是的,宏是邪恶的。但它们可以很容易地解决这样的问题。
#define DefineChild(CLASS,ID)\
struct CLASS :public Base {\
const char * getID(){\
return ID; \
} \
}
DefineChild(Child1,A);
DefineChild(Child2,B);
代码生成
生成基类对于构建脚本中的每个子类。 (或者甚至每个子类直接,如果他们是空的,你说)。
定义文件 - 这是你如何配置生成的东西。
Child1A
Child2B
Child3C
...
- 生成脚本的输出
//生成的代码 - 不要编辑
struct Child1Base:public Base {
const char * getID(){returnA; }
}
...
应用程序代码 -
如果需要,生成的代码。
struct Child1:public Child1Base {}
struct Child2: public Child2Base {}
struct Child3:public Child3Base {}
struct Child4:public Child4Base {}
Hello I have a global array of let's say
array = ["A", "B", "C", "D", "E"]
I want to design a parent class with 5 children classes like this
Parent, Child1, Child2, Child3, Child4, Child5
The Parent class will have a method name getID();
How can i design such that this behavior occur
Child1.getID() is array[0] gives "A"
Child2.getID() is array[1] gives "B"
Child3.getID() is array[2] gives "C"
Child4.getID() is array[3] gives "D"
Child5.getID() is array[4] gives "E"
Is this possible?
The reason is that I don't want to keep copy and pasting getID() for 5 children. It would be nice to just write getID() in parent class.
I'm going to assume that the aim is to avoid repetition of the body of getID()
in each child class. But I also think moving the array into the parent class is "not ideal".
There are many options you can use to avoid the boilerplate code. Which one works best for you depends heavily on the real use case for the classes.
Use only one child class and a factory method in parent
Push the common code into a base class and add a factory method to the parent class (You could even merge the parent class and base class if appropriate).
struct ChildBase : public Base {
explicit ChildBase(const char* name) : name(name) {};
const char * name;
const char * getID() { return name; }
}
struct Base {
ChildBase getChild1() { return ChildBase("A"); }
ChildBase getChild2() { return ChildBase("B"); }
}
or even
struct Base {
const char* ids = { "A", "B", "C", ...};
ChildBase getChild(int i) { return ChildBase(ids[i]); }
}
This second form easily generalizes to loading the configuration at run time.
Use a base class
Push the common code into a base class.
Usually this would look like:
struct ChildBase : public Base {
ChildBase(const char* name) : name(name) {};
const char * name;
const char * getID() { return name; }
}
struct Child1 : public ChildBase {
Child1() : ChildBase("A") {};
}
struct Child2 : public ChildBase {
Child2() : ChildBase("B") {};
}
but this doesn't save you much since you still need to customize the constructor. You can reduce the cruft using a templated base class instead
template<const char* ID>
struct ChildBase() {
const char* getID() { return ID; }
};
struct Child1 : public ChildBase<"A">();
struct Child2 : public ChildBase<"B">();
Macros
Yes, macros are evil. But they can solve a problem like this pretty easily
#define DefineChild(CLASS, ID) \
struct CLASS : public Base { \
const char * getID() { \
return ID; \
} \
}
DefineChild(Child1, "A");
DefineChild(Child2, "B");
Code Generation
Generate a base class for each of the child classes in your build script. (Or even each of the child classes directly if they're as empty as you say.)
Definition File - this is how you configure what gets generated. You'll need to write a generation script, but that can usually be pretty trivial.
Child1 "A"
Child2 "B"
Child3 "C"
...
Generated code - The output of your generation script
// Generated code - do not edit
struct Child1Base : public Base {
const char* getID() { return "A"; }
}
...
Application Code - Here you can customize the behaviour of the generated code if needed.
struct Child1 : public Child1Base {}
struct Child2 : public Child2Base {}
struct Child3 : public Child3Base {}
struct Child4 : public Child4Base {}
这篇关于C ++继承与父“知道”这些孩子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!