简体   繁体   English

C ++中具有多个参数类型的虚拟方法

[英]Virtual methods with multiple argument types in C++

Lets say I have a base class A that I want to have a method getName that can take in either an integer or a string as the argument. 可以说我有一个基类A,我想要一个方法getName可以接受整数或字符串作为参数。 So I create: 所以我创建:

virtual string getName(int index) = 0;
virtual string getName(string key) = 0;

Now, I want to create two different subclasses B and C. B only needs the getName(int index) and C only needs the getName(string key) . 现在,我想创建两个不同的子类B和C。B只需要getName(int index)而C只需要getName(string key) However, if I dont overwrite both methods in both subclasses, I get an error. 但是,如果我不覆盖两个子类中的两个方法,则会收到错误消息。 But if I do this, then B and C will have an empty methods because they dont need the other case of getName 但是,如果我这样做,那么B和C将有一个空方法,因为它们不需要getName的另一种情况

How can I overcome this problem? 我该如何克服这个问题?

It sounds like you actually want two different interfaces: one that supports getName(int) and one that supports getName(string) . 听起来您实际上需要两个不同的接口:一个支持getName(int) ,另一个支持getName(string)

struct GetNameInt {
    virtual string getName(int index) = 0;
};

struct GetNameStr {
    virtual string getName(string key) = 0;
};

struct B : GetNameInt { /* ... */ };
struct C : GetNameStr { /* ... */ };

If you really need a single base class with the same interface, and you only know at run-time whether you'll need a string or an int , you might want to use std::variant : 如果确实需要具有相同接口的单个​​基类,并且仅在运行时知道需要string还是int ,则可能需要使用std::variant

struct GetName {
    virtual string getName(std::variant<int, string>) = 0;
};

You're not using inheritance properly. 您没有正确使用继承。 I strongly recommend reading more about the SOLID principles . 我强烈建议您阅读有关SOLID原则的更多信息。

You need to split the class A into two classes (interfaces) - Aa and Ab, where Aa would hold getName(int index) and would have getName(string key), like: 您需要将类A分为两个类(接口)-Aa和Ab,其中Aa将保存getName(int索引)并具有getName(string键),例如:

class A {
//does not define neither of the getName methods
}

class Aa {
    virtual string getName(int index) = 0;
}

class Ab {
    virtual string getName(string key) = 0;
}

class B : A, Aa {
    //inherits from A and defines string getName(int index)
}

class C : A, Ab {
    //inherits from A and defines string getName(string key)
}

Ok, the best I can come up with to keep a common parent between B and C while still preserving some type safety and compile time check: 好的,我想出的最好的办法是在B和C之间保持一个公共父级,同时仍然保留一些类型安全性和编译时间检查:

struct CommonA //protect this if possible
{
    template<class type>
    string getGenericName(type index);
    virtual ~CommonA() {}
};

template<class indexType>
struct A : CommonA
{
    virtual string getName(indexType index) = 0;
};

struct B : A<int>
{
    string getName(int index) override {cout << index << "\n"; }
};
struct C : A<string>
{
    string getName(string index) override {cout << index << "\n"; }
};

template<class type>
string CommonA::getGenericName(type index)
{
    cout << "generic call: \n"; 
    return dynamic_cast<A<type>*>(this)->getName(index);
}

int main()
{
  CommonA b = B();
  CommonA c = C();
  b.getGenericName(1);
  c.getGenericName(string("hello world"));
}

Note that this solution is not a standard OOP solution but a template solution. 请注意,此解决方案不是标准的OOP解决方案,而是模板解决方案。

Edit: my templated A<> class is the same as Vittorio Romeo's solution using template instead of name pasting (name pasting is evil) 编辑:我的模板化A <>类与使用模板而不是名称粘贴的Vittorio Romeo的解决方案相同(名称粘贴是邪恶的)

By simply don't making them pure virtual, but just virtual: 通过简单地使它们不是纯虚拟的,而是纯虚拟的:

struct Blub
{
    virtual void do1() {} // default definition
    virtual void do2() = 0; //has to be overridden
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM