C ++继承与父“知道”这些孩子 [英] C++ Inheritance with parent "knowing" the children

查看:158
本文介绍了C ++继承与父“知道”这些孩子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆