C++ 我的虚拟功能应该是什么';什么是原型?

C++ 我的虚拟功能应该是什么';什么是原型?,c++,oop,function-prototypes,C++,Oop,Function Prototypes,假设我有一个抽象基类base,带有一个虚拟函数doSomething() 有两个派生类,其中一个在doSomething()中不接受任何参数,而另一个接受结构和整数作为参数 另一个类(SomeClass)中的函数使用Base*变量调用doSomething()。 它还需要传递我提到的DerivedTwo的参数 如何选择原型而不使用if-else在运行时检查对象的类 多谢各位 class Base { public: void virtual doSomething

假设我有一个抽象基类
base
,带有一个虚拟函数
doSomething()

有两个派生类,其中一个在
doSomething()
中不接受任何参数,而另一个接受结构和整数作为参数

另一个类(SomeClass)中的函数使用
Base*
变量调用
doSomething()
。 它还需要传递我提到的
DerivedTwo
的参数

如何选择原型而不使用if-else在运行时检查对象的类

多谢各位

    class Base {
      public:
      void virtual doSomething(); 
    }

    class DerivedOne : Base {
      public:
      void doSomething(int a,struct b);
    }

    class DerivedTwo : Base {
      public:
      void doSomething();
    }

如果需要为两个派生类型传递这些变量,只需在所有地方声明它们相同,如下所示:

class Base {
  public:
  void virtual doSomething(int a,struct b); 
}

class DerivedOne : Base {
  public:
  void doSomething(int a,struct b);
}

class DerivedTwo : Base {
  public:
  void doSomething(int a,struct b);
}

如果您需要为一种类型使用参数,而不是为另一种类型使用参数,那么您需要的不是类层次结构。在这种情况下,您需要详细说明您的问题。

一种方法是:

class Base {
public:
    Base();
    virtual ~Base();
    virtual void doSomething();
};

class DerivedOne : public Base {
public:
    DerivedOne();
    void doSomethingElse(int a,struct b);
};

class DerivedTwo : public Base {
public:
    DerivedTwo();
    virtual void doSomething();
};
class Base {
public:
    Base();
    virtual ~Base();
    virtual void doSomething();
};

class DerivedOne : public Base {
public:
    DerivedOne();
    // ...
    virtual void doSomething(); // << no parameters required.
                                // they have moved to member data:
private:
    int a;
    b another;
};

class DerivedTwo : public Base {
public:
    DerivedTwo();
    virtual void doSomething();
};
然后可以使用
dynamic\u cast
在运行时确定类型,因为在
SomeClass
中似乎有一个类型条件表达式。这两种方法并不相同,而且根本不同。而且,
DerivedOne::doSomething
将隐藏
Base::doSomething

更新

正如其他人已经说过的,如果您的程序依赖类型条件表达式,这通常是一个坏消息。由于您的示例没有足够的上下文来提供适当的解决方案,因此我们很难在这方面帮助您。如果您有兴趣删除条件类型,此问题的许多潜在解决方案之一是:

class Base {
public:
    Base();
    virtual ~Base();
    virtual void doSomething();
};

class DerivedOne : public Base {
public:
    DerivedOne();
    void doSomethingElse(int a,struct b);
};

class DerivedTwo : public Base {
public:
    DerivedTwo();
    virtual void doSomething();
};
class Base {
public:
    Base();
    virtual ~Base();
    virtual void doSomething();
};

class DerivedOne : public Base {
public:
    DerivedOne();
    // ...
    virtual void doSomething(); // << no parameters required.
                                // they have moved to member data:
private:
    int a;
    b another;
};

class DerivedTwo : public Base {
public:
    DerivedTwo();
    virtual void doSomething();
};
类基{
公众:
Base();
虚拟~Base();
虚空剂量仪();
};
类DerivedOne:公共基{
公众:
衍生酮();
// ...

virtual void doSomething();//您想要更改派生类中虚拟方法的参数列表。这无法完成。通常,当您发现自己想要这样做时,这表明您的类层次结构设计不正确

解决这一问题的幼稚尝试通常包括向基类中添加仅对某些派生类有意义的内容。这违反了良好设计的原则


有许多不同的方法可以更恰当地解决这个问题,但很难根据这个人为构建的示例提出建议。

我们可以这样解决这个问题吗?:

class Base {
  public:
  void virtual doSomething();
  void virtual doSomething(int a,struct b); 
}

class DerivedOne : Base {
  public:
  void doSomething(int a,struct b);
}

class DerivedTwo : Base {
  public:
  void doSomething();
}

在您的示例中,您可以使用RTTI而不是if/else,因此您可以实例化DerivedOne和DerivedTwo,然后将基指针强制转换为这两个(DerivedOne和DerivedTwo),这样结果就是其中一个为NULL。然后检查所需的派生对象是否为NULL,如果是,则调用函数:

DerivedOne *pDrvOne=dynamic_cast<DerivedOne*>(pBase);
DerivedTwo *pDrvTwo=dynamic_cast<DerivedTwo*>(pBase);
then: if(pDrvOne)pDrvOne->deSo,ething(a,b); if(pDrvTwo) pDrvTwo->doSomething();

*解决方法是尝试理解您的类将要解决的问题。

类似于塔拉斯的示例。只需在塔拉斯的示例中为Base和derivedtou的原型添加“默认值”。这样,使用基类或derivedtou类的其余代码就不必更改。

您能比
Base更具体一点吗de>,
DerivedOne
derivedtow2
?我解决这个问题的方法是简单地制作
Base::doSomething()
接受一个
struct
和一个
int
。但是如果原型不同,我倾向于认为设计有一个基本问题。
如果
/
其他
语句对于这种情况几乎总是错误的答案。谢谢。在doSomething()中不传递参数是一个好的做法吗而是为它们提供getter。如果派生类需要,可以使用它们。@Pramod:我不能根据这个肤浅的示例来评论不传递参数是好还是坏的做法。这取决于您的实际问题。在基类中键入条件代码以测试实例是哪个派生类是一个很好的方法jor设计缺陷。@DavidHeffernan我同意你的看法,但这里不是这样;OP指定的类型条件发生在
SomeClass
的实现中。由于函数调用的目标是Base*,因此它相当于一个。无论如何,我只想指出,尽管这是公认的答案,但原始问题a这个直接的答案有一点糟糕的设计。David就在这里,无论是在
Base
还是在调用者的代码中,事实是如果必须知道
DerivedOne
的类型才能调用不同的方法/重载,这显然违反了Liskov的替换原则。需要注意的是,接口不仅仅是方法的名称,还有签名和语义。有一次给我举了一个例子:相机和手枪都可以射击,但在拍摄自画像之前要小心手中的东西,在这种特殊情况下,界面更加不同:
shoot(Picture&)
shoot(Bullet&)
@DavidHeffernan我也不喜欢这种设计。但是出现这种情况是因为我们将代码移植给了几个供应商。每个供应商都为自己的API提供了自己的原型。所以完整的设计不在我的团队手中