【问题标题】:Create a variable to hold objects of different types C++创建一个变量来保存不同类型的对象 C++
【发布时间】:2017-08-23 05:22:08
【问题描述】:

我有 3 个不同的对象 ABC。根据给定的参数,我想在这些不同的对象中进行选择。在编程中,

class A { 
  public: 
    void printHello() { cout << "HELLO A" << endl; }
}; 

class B { 
  public: 
    void printHello() { cout << "HELLO B" << endl; }  
};

class C { 
   public: 
     void printHello() { cout << "HELLO C" << endl; }  
}; 

int main () { 
    string key = "c"; 
    A a; 
    B b; 
    C c; 
    Object obj; // I don't know how to declare Object. 

    if (key == "a") obj = a; 
    else if (key == "b") obj = b; 
    else obj = c;
    obj.printHello(); // print Hello C.
    return 0; 
} 

我考虑过模板和结构对象。但到目前为止,它们都没有工作。

template<typename T1, T2, T3> 
T1 getType(string key, T1 t1, T2 t2, T3 t3) { // this is problem coz return types are different.
    if (key == "a") return t1; 
    else if (key == "b") return t2; 
    else return t3; 
} 

JAVA 中创建Object o; 很容易,因为Java 中的每个对象都是Object 类的子类。但是如何在 C++ 中实现这一点?

编辑。 我无法更改课程ABC。我得到了这些类来使用,我的目标是实现main 方法。所以,inheritance 对我来说是不可能的。很抱歉有任何混淆。

感谢任何帮助。

【问题讨论】:

  • 好像是继承?
  • 在 Java 中,每个类都隐式继承自 Object。您可以通过自己编写抽象类Object 在 C++ 中模拟同样的事情。
  • 看看std::any
  • 您不需要所有东西都继承自的Object 类。你只需要你自己的基类,所有你的类都继承自。
  • 您甚至不需要将您的类型与基类耦合。变体是这种情况的完美解决方案。

标签: c++ c++11 templates object variable-declaration


【解决方案1】:

您正在寻找variant 类型。在 C++17 中有一个即将发布的 std::variant,在 boost 和网络上发布了符合 C++11 的版本。以boost::variant 为例:

struct visitor
{
    void operator()(const A&){ cout << "HELLO A" << endl; }
    void operator()(const B&){ cout << "HELLO B" << endl; }
    void operator()(const C&){ cout << "HELLO C" << endl; }
};

int main()
{
    visitor v;

    // `obj` is either an `A`, a `B` or a `C` at any given moment.
    boost::variant<A, B, C> obj{B{}};
    //                         ^^^^^
    //                   Initialize with `B`.

    boost::apply_visitor(v, obj); // prints "HELLO B"

    obj = A{};
    boost::apply_visitor(v, obj); // prints "HELLO A"
}

【讨论】:

  • 很好地回答了这个问题......但很明显,通过学习继承可以更好地服务于 OP
  • @Nemo Ehm,不,根本不清楚。也许对于其他一些实际需要继承的用例。
  • 这看起来像我正在寻找的答案。让我先尝试一下并接受它作为答案。
  • @pseudo:很高兴听到这个消息。如果您对变体和类似概念感兴趣,您应该查看Ben Deane's "Using types effectively" talk。我还写了a few articles about "variant visitation with lambdas"
【解决方案2】:

在我看来,您应该使用虚拟公共基类/结构和指向该基类/结构的指针。

以下是一个完整的工作示例

#include <iostream>

struct Base
 { virtual void printHello () = 0; };

class A : public Base { 
  public: 
    void printHello() { std::cout << "HELLO A" << std::endl; }
}; 

class B  : public Base{ 
  public: 
    void printHello() { std::cout << "HELLO B" << std::endl; }  
};

class C  : public Base{ 
   public: 
     void printHello() { std::cout << "HELLO C" << std::endl; }  
}; 

int main () { 
    std::string key = "c"; 
    A a; 
    B b; 
    C c; 
    Base * obj; 

    if (key == "a") obj = &a; 
    else if (key == "b") obj = &b; 
    else obj = &c;
    obj->printHello(); // print Hello C.
    return 0; 
} 

【讨论】:

  • 如果 OP 事先知道所有类型,那么 virtual 与变体相比是次优的:它可能会对性能产生负面影响,并且还会强制所有类型的接口相同。此外,您应该将printHello 标记为override
  • @VittorioRomeo - 你是对的;不幸的是,std::variant 只能从 C++17 开始使用(但使用 boost::variant 很好);无论如何......也许我错了......但在我看来,OP 并不知道 C++ 是已知的 Java,并且应该了解如何使用虚拟继承
【解决方案3】:

你可以做类似的事情

if (key == "a") obj=new A();
else if (key == "b")  obj=new B();

【讨论】:

  • 如果 'obj' 是指向基类实例的指针,这将起作用,但在问题中,这 3 个类之间没有任何关系,只是它们实现了相同的功能。
  • 没有回答实际的原始问题,你能改进一下吗?谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-21
  • 2014-12-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多