【问题标题】:C++: Initialize an array of pointers to objects with different typesC ++:初始化指向具有不同类型的对象的指针数组
【发布时间】:2017-06-14 06:43:24
【问题描述】:

C++ 中是否有一种语法来初始化指向具有不同类型的对象的指针数组而无需额外分配?我试图在下面提供一个完整的示例。

#include "stdio.h"

class Base {
    public:
        Base(int cnt=1) : _cnt(cnt) {}
        virtual void print() { printf("?\n"); }
    protected:      
        int _cnt;       
};      

class A : public Base {     
    public:     
        A(int val, int cnt=1) : _val(val), Base(cnt) {}
        void print() override { for (int i=0; i<_cnt; i++) printf("A(%d)\n", _val);  }
    private:
        int _val;
};

class B : public Base {
    public:
        B(const char* val, int cnt=1) : _val(val), Base(cnt) {}
        void print() override { for (int i=0; i<_cnt; i++) printf("B(\"%s\")\n", _val);  }
    private:
        const char* _val;
};

//  *** I would like to combine the following statements ***
A a = { 42, 2 };
B b = { "hi there", 3 };

Base* test[] = { &a, &b };

int main() {
    for (auto *x : test) { x->print(); }
}

当我尝试时

Base* test2[] = {
    &A(42, 2), 
    &B("hi there", 3),
};

获取临时地址时出现错误。代码需要在小型嵌入式系统上运行代码,所以我尽量避免动态分配。

希望这不是常见问题解答 ...

感谢您的帮助!

【问题讨论】:

  • 不是没有动态分配
  • 错误消息准确地说明了问题所在。使用new A(42,2)。更好地使用智能指针
  • 类型集有多大?它是开放的还是封闭的?
  • @StoryTeller:大约有 10 种不同类型的对象。
  • 还有可以随时添加的吗?还是这组类型是封闭的?

标签: c++ arrays initialization


【解决方案1】:

您的帖子提到您需要值语义,这意味着没有动态分配。在您提到的 cmets 中,您的类型集是封闭的。因此,您可以使用boost::variant 进行闭集多态。

using common_t = boost::variant<A, B>;

common_t arr[] = {
    A(42, 2), 
    B("hi there", 3),
};

好消息是这些类型不再需要有一个共同的基础。他们只需要尊重相同的接口(有print)。您基本上用静态多态性替换动态。现在可以使用通用 lambda 访问任何成员

for(auto &obj : arr)
  boost::apply_visitor([](auto& o) {
    o.print();
  }, obj);

【讨论】:

  • 刚刚看了一下 boost::variant ,它看起来很棒!但是,Boost 似乎不适用于目标系统 :-( 我想 +1 你的答案,但我的声誉还不够高。
  • @Matthias - 好吧,这很不幸。 Boost 在我看来非常棒。如果平台考虑不适用,我确实相信这是解决您的问题的最佳解决方案。不要担心投票,我很高兴我能以某种方式提供帮助。
【解决方案2】:

在你的例子中:

Base* test2[] = {
    &A(42, 2), 
    &B("hi there", 3),
};

AB 都在数组初始值设定项的范围内被实例化。它们在此范围内是临时的,这就是编译器不允许您将它们存储在数组中的原因。

您应该使用智能指针来动态分配您的对象,因为在其范围之外访问堆栈变量是不安全的。

智能指针的一个很好的例子是shared_ptrhttp://en.cppreference.com/w/cpp/memory/shared_ptr

【讨论】:

  • 感谢您的提示!但是,我忘了提到代码需要在资源非常有限的小型嵌入式系统上运行。
  • @Matthias 在这种情况下,将数组更改为存储Base(不是Base *),您可以按照您在示例中所做的方式实例化它们,当然没有&amp; .
  • 你的意思是像这样@snoopy? Base test2[] = { A(42, 2), B("hi there", 3), }; 但是,我收到以下错误:unable to deduce 'auto*' from '* __for_begin' for (auto *x : test2) {
  • @Matthias 编译错误与原来的问题无关,实际上你原来的问题似乎已经解决了。只需删除语句auto *x : test 中的*,就可以正常编译。这是因为您不再存储指针。
  • 你是对的@snoopy - 这是另一回事。如果我将语句更改为 for (auto x : test2) { x.print(); } 它编译得很好。但是,输出是 ? ?现在。
猜你喜欢
  • 1970-01-01
  • 2014-03-14
  • 1970-01-01
  • 2013-06-30
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-23
相关资源
最近更新 更多