C++ C++;继承与确定类型

C++ C++;继承与确定类型,c++,inheritance,polymorphism,C++,Inheritance,Polymorphism,因此,我正在从事一个个人项目(努力提高c++水平),我正在努力使这项工作正常进行: 我有ABC A班 与纯虚拟函数交互(a*目标) 然后我有两个派生类,类B和类C 但是,类B与类C的交互方式必须不同于与另一个类B的交互方式 我在ABC中找到了一种使用if/else和虚拟getType()的方法,但我很好奇是否有更优雅的方法,或者我只是在做一些非常愚蠢的事情,如果我在做一些愚蠢的事情(这是非常可能的),我从哪里开始寻找更好的解决方案(即更合适的设计模式) 请注意:我没有使用boost,我现在宁愿避

因此,我正在从事一个个人项目(努力提高c++水平),我正在努力使这项工作正常进行:

我有ABC A班 与纯虚拟函数交互(a*目标)

然后我有两个派生类,类B和类C

但是,类B与类C的交互方式必须不同于与另一个类B的交互方式

我在ABC中找到了一种使用if/else和虚拟getType()的方法,但我很好奇是否有更优雅的方法,或者我只是在做一些非常愚蠢的事情,如果我在做一些愚蠢的事情(这是非常可能的),我从哪里开始寻找更好的解决方案(即更合适的设计模式)

请注意:我没有使用boost,我现在宁愿避免使用它,在我真正擅长编程的时候开始学习它

欢迎您提供任何帮助。请,谢谢

我应该注意的是:B类和C类将(应该)只能通过A*

使用动态强制转换看到

C* cTarget = dynamic_cast<C*>(target);
if(cTarget == NULL)
{
    //cTarget is not a C
}
else if(cTarget)
{
    //cTarget is a C
}
C*cTarget=dynamic_cast(目标);
if(cTarget==NULL)
{
//cTarget不是C
}
else if(cTarget)
{
//cTarget是一个C
}
dynamic\u cast做了一些奇特的事情(我不确定它是做什么的),以确保强制转换是有效的,如果不是,它将返回NULL。

使用dynamic\u cast

C* cTarget = dynamic_cast<C*>(target);
if(cTarget == NULL)
{
    //cTarget is not a C
}
else if(cTarget)
{
    //cTarget is a C
}
C*cTarget=dynamic_cast(目标);
if(cTarget==NULL)
{
//cTarget不是C
}
else if(cTarget)
{
//cTarget是一个C
}

dynamic_cast做了一些奇特的事情(我不确定它是做什么的)来确保强制转换是有效的,如果不是,它将返回NULL。

您试图实现的是:一个函数,它对两个对象的行为就像虚拟的一样

有几种方法可以实现它,其中一种更常见的方法是使用


斯科特·梅耶斯(Scott Meyers)有一章介绍了如何实现双重分派(他的书中第31项)。他首先讨论访问者模式,然后讨论一个非常好的实现。

您试图实现的是:一个对两个对象表现为虚拟的函数

有几种方法可以实现它,其中一种更常见的方法是使用


斯科特·梅耶斯(Scott Meyers)有一章介绍了如何实现双重分派(他的书中第31项)。他首先讨论了访问者模式,然后讨论了一个非常好的实现。

您几乎不想使用类型切换。动态铸造稍微好一点,但如果可能的话仍然要避免

更好的选择是扭转局面,以便再次使用虚拟调度机制,通常称为“双重调度”或“模拟多种方法”。它看起来像这样:

struct B;

struct A { 
  virtual void interactWith(A* target); 
  virtual void interactWithB(B* target);
};

struct B : A {
  virtual void interactWith(A* target) {
    target->interactWithB(this);
  }
  virtual void interactWithB(B* lhs) {
    // B vs. B stuff goes here, but with lhs and this in place of this and target
  }
};

struct C : A {
  virtual void interactWith(A* target) {
    // C vs. anything stuff goes here
  }
  virtual void interactWithB(B* lhs) {
    // B vs. C stuff goes here, again backward
  }
};

你几乎不想使用类型转换。动态铸造稍微好一点,但如果可能的话仍然要避免

更好的选择是扭转局面,以便再次使用虚拟调度机制,通常称为“双重调度”或“模拟多种方法”。它看起来像这样:

struct B;

struct A { 
  virtual void interactWith(A* target); 
  virtual void interactWithB(B* target);
};

struct B : A {
  virtual void interactWith(A* target) {
    target->interactWithB(this);
  }
  virtual void interactWithB(B* lhs) {
    // B vs. B stuff goes here, but with lhs and this in place of this and target
  }
};

struct C : A {
  virtual void interactWith(A* target) {
    // C vs. anything stuff goes here
  }
  virtual void interactWithB(B* lhs) {
    // B vs. C stuff goes here, again backward
  }
};

理想情况下,封装与B和C交互时需要不同的行为,并将其放入另一个调用
target
的虚拟方法中——然后在B和C中根据需要对该方法进行不同的实现


如果上述内容过于混乱和分散,则表明您选择了错误的抽象作为对象。您最好放弃A/B/C类层次结构,并将程序划分为不同的层次结构,但如果没有对您试图做的事情进行更具体的描述,那就很难说了。过早的抽象(以及过早的优化)是缺乏经验的程序员经常犯的主要错误之一。

理想情况下,封装与B和C交互时需要不同的行为,并将其放入另一个调用
target
的虚拟方法中——然后在B和C中根据需要对该方法进行不同的实现


如果上述内容过于混乱和分散,则表明您选择了错误的抽象作为对象。您最好放弃A/B/C类层次结构,并将程序划分为不同的层次结构,但如果没有对您试图做的事情进行更具体的描述,那就很难说了。过早的抽象(以及过早的优化)是缺乏经验的程序员经常犯的主要错误之一。

“然而,类B与类C的交互方式必须不同于与另一个类B的交互方式”-为什么?您考虑过多态函数吗?“然而,类B与类C的交互方式必须不同于与另一个类B的交互方式”-为什么?你有没有考虑过多态函数?比我的答案好,还有几秒钟之前…谢谢你的参考资料。他们比我的答案更有用,而且几秒钟前也是如此……谢谢你的推荐。他们非常乐于助人这通常是错误的做法。此外,除非您对dynamic_cast的“奇特功能”有一些模糊的了解,否则您真的不应该依赖dynamic_cast(仅在单继承的情况下检查rtti,但在涉及多个继承图的情况下检查rtti)。这通常是错误的做法。此外,你真的不应该依赖dynamic_cast,除非你至少对它所做的“奇特的事情”有一些模糊的理解(这只涉及在单个继承的情况下检查rtti,但在涉及多个继承图的情况下检查rtti)。+1好吧,这里有一些代码,这是迟到几秒钟的一个很好的理由:)+1好吧,这里有一些代码,这是迟到几秒钟的一个很好的理由:)