在c ++中动态转换**数组

时间:2018-06-02 18:44:01

标签: c++ downcast

我正在尝试创建一个读取多态动态数组的函数,并为每个类打印不同的东西。代码是这样的:

class A {};
class B: public A {};
class C: public A {};

void function (const A &a) {
    if(B *b = dynamic_cast<B*>(a)){
        cout << "B" << endl;
    }
    if(C *c = dynamic_cast<C*>(a)){
        cout << "C" << endl;
    }
}

int main () {
    A **array = new A* [2];
    array [0] = new B;
    array [1] = new C;

    function (array [0]); // To print B
    function (array [1]); // To print C
}

但它给了我一个错误说:

cannot dynamic_cast ‘a’ (of type ‘const class A’) to type ‘class B*’ (source is not a pointer)

我该怎么办?

3 个答案:

答案 0 :(得分:3)

将动态广告代码应用于a的地址,例如dynamic_cast<const B*>(&a)。虽然引用是指针下的指针(有点),但你不能把它当作指针。

但是,我建议不要写这样的东西,它不会缩放。

PS - 正如评论者所说,你需要动态转换为const指针,而你的示例转换为非const。

答案 1 :(得分:2)

正如其他人所说,为什么不跳过演员?此外,如果你希望你的派生类表现出不同的行为,为什么不明确定义不同的行为?也就是说,使用dynamic_cast<>说明你的意图 - 替代方案也是如此。

话虽如此,正如其他人所说,你的基类应该至少有一个virtual函数,你的派生类应该是公开派生的。

class A {
public:
    virtual void operator()() {
        std::cout << "A\n";
    }

    virtual void print() {
        std::cout << "A\n";
    }

    virtual ~A() = default;
};

class B : public A {
public:
    void operator()() override {
        std::cout << "B\n";
    }

    void print() override  {
        std::cout << "B\n";
    }
};

class C : public A {
public:
    void operator()() override {
        std::cout << "C\n";
    }

    void print() override {
        std::cout << "C\n";
    }
};

int main()
{
    std::vector<A*> v;
    auto pa = new A{};
    auto pb = new B{};
    auto pc = new C{};

    v.push_back(pa);
    v.push_back(pb);
    v.push_back(pc);

    for(auto& elem : v)
        elem->print();

    delete pa;
    delete pb;
    delete pc;

    return 0;
}

我认为这是你问题答案的一部分。我相信你问题的另一部分可以回答:

std::vector<A> vv;
A a;
B b;
C c;

a(); // A
b(); // B
c(); // C

vv.push_back(a);
vv.push_back(b);
vv.push_back(c);

for(auto& elem : vv)
    elem(); // ?

答案 2 :(得分:1)

我修改了你的代码,以便按你想要的方式工作。但我建议您不要这样做:使用new / deletenew[] / delete[]和原始指针不是最佳做法。使用dynamic_cast是一种非常糟糕的代码味道。

#include <iostream>

using std::cout;
using std::endl;

namespace
{

class A
{
public:
  virtual ~A() = default;
};

class B: public A
{
};

class C: public A
{
};

void function (A const& a)
{
  if (B const* b = dynamic_cast<B const*>(&a))
  {
    cout << "B" << endl;
  }

  if (C const* c = dynamic_cast<C const*>(&a))
  {
    cout << "C" << endl;
  }
}

} // anonymous namespace

int main ()
{
  A* array[2] =
  {
    new B,
    new C
  };

  function(*array[0]); // To print B
  function(*array[1]); // To print C
}