18

下面的代码片段会产生错误:

#include <iostream>

using namespace std;

class A
{

public:

  virtual void print() = 0;
};

void test(A x) // ERROR: Abstract class cannot be a parameter type
{
  cout << "Hello" << endl;
}

是否有解决此错误的解决方案/解决方法/比替换更好

virtual void print() = 0;  

virtual void print() = { }

编辑:我希望能够通过使用多态性(即 A* x = new B() ; test(x);)传递任何扩展/实现基类 A 作为参数的类

干杯

4

3 回答 3

32

因为你不能实例化一个抽象类,所以传递一个值几乎肯定是一个错误;您需要通过指针或引用传递它:

void test(A& x) ...

或者

void test(A* x) ...

按值传递将导致对象切片,几乎可以保证会产生意想不到的(以不好的方式)后果,因此编译器将其标记为错误。

于 2012-07-10T21:16:33.483 回答
3

当然,更改签名:

void test(A& x)
//or
void test(const A& x)
//or
void test(A* x)

您的版本不起作用的原因是类型对象在A逻辑上没有意义。很抽象。传递引用或指针可以解决这个问题,因为作为参数传递的实际类型不是A,而是A(派生的具体类)的实现类。

于 2012-07-10T21:16:10.730 回答
0

绝对清楚,问题是,每当您定义一个类时:

#include <iostream>

class foo {
  public:
    char *name = (char *)"foo";
};

并将该类的实例传递给函数,它会创建一个副本:


void bar(foo a) {
  a.name = (char *)"bar";
}

int main() { 
  foo x;
  bar(x);
  std::cout << x.name << std::endl; // foo
  return 0;
}

关于继承,它创建一个副本作为基类的实例:

#include <iostream>

class foo {
  public:
    char *name = (char *)"foo";
};

class bar: public foo {
  public:
    char *name = (char *)"bar";
};

void baz(foo a) {
  std::cout << a.name << std::endl;
}

int main() { 
  bar x;
  baz(x); // again, foo
  return 0;
}

所以,通过这样做

void baz(AbstractType a) {
  ...
}

您是在告诉编译器将 a 复制AbstractType为自身的实例AbstractType,这是非法的。传递它const AbstractType &a以防止复制。

于 2020-06-18T15:27:41.790 回答