【问题标题】:cannot declare variable to be of type because the following virtual functions are abstract无法将变量声明为类型,因为以下虚函数是抽象的
【发布时间】:2013-03-09 23:14:26
【问题描述】:

我有以下代码

类.h

#ifndef CLASSES_H
#define CLASSES_H

#include <iostream>
using namespace std;



template< class T1, class T2>
class class1
{
      public:
             virtual void method1(int) const =0;
             virtual void method2(class1&) const =0;
};


template< class T1>
class class2:public class1<T1,int>
{
      public:
             void method1(int) const;
             void method2(class2&) const;
};


template< class T1>
void class2<T1>::method1(int i) const
{
     cout<<"class2::method1 - before Call %i"<<endl;
     cout<<"class2::method1 - after Call"<<endl;
}

template< class T1>
void class2<T1>::method2(class2& c2) const
{
     cout<<"class2::method2 - before Call"<<endl;
     cout<<"class2::method2 - after Call"<<endl;
}

#endif

main.cpp

#include <cstdlib>

#include <iostream>
using namespace std;

#include "Classes.h" 

int main(int argc, char *argv[])
{
    class2<int> c2;

    c2.method1(0);
    c2.method2(c2);

    system("PAUSE");
    return EXIT_SUCCESS;
}

基本上,C1 是一个接口类,因此它的方法是纯虚拟的。遇到的问题是 Medhod2 传递和类本身的实例(接口是 class1,实现此类接口的类是 class2)。

因此 Method2 有签名

void method2(class1&) const;

在class1和

void method2(class2&) const;

在第 2 类中。

这就是我在编译时收到以下错误的原因。

main.cpp: In function `int main(int, char**)':
main.cpp:12: error: cannot declare variable `c2' to be of type `class2<int>'
main.cpp:12: error:   because the following virtual functions are abstract:
Classes.h:14: error:  void class1<T1, T2>::method2(class1<T1, T2>&) const [with
T1 = int, T2 = int]
make: *** [main.o] Error 1

我该如何解决这个问题?

有人可以告诉我吗?谢谢。

【问题讨论】:

  • 不要写using namespace std;。它违背了将标准库放在命名空间中的目的。而且,更重要的是,不要将其写在标题中;你会搞砸每一个试图使用你的类的程序员。
  • @Pete Becker 我知道。我只是为了这个例子而使用它。你对我的问题有何建议?
  • 我发现很难弄清楚这里要问什么。您似乎想要做的事情无法在 C++ 中完成,但我怀疑如果我们知道您的潜在需求,模板或替代虚拟方法将解决您的实际问题。您能否详细说明您的真正问题,而不是实现的一小部分?

标签: c++ class inheritance interface virtual


【解决方案1】:

您的问题是虚拟签名需要匹配(返回类型可以是协变的,但否则签名应该相同)。将 class2 的 void method2(class2&amp;) const; 更改为 void method2(class1&amp;) const;

或者,隐藏虚拟方法并提供替代方法:

class class2
{
    // must be implemented since pure virtual, but now private
    void method2(class1&) const; 
public:
    void method1(int) const;
    void method2(class2&) const;
};

【讨论】:

  • 好吧,我不明白。我自己在帖子中写道。但是问题是在 class2::method2 中传递的参数必须是 class2 的实例。不能是从 class1 派生的任何其他类型的类。您的解决方案在语法上是正确的,并且可以编译;但是代码在语义上不会是正确的。你是怎么得到其他建议的?
  • @gerald 没有办法做你想做的事,因为class2不遵循你刚刚在class1中定义的接口。使用接口的时候,怎么知道应该传入class2、class3还是class4作为参数呢?
  • @Bo Persson 我正在考虑一些向下转型 - 向上转型机制来做到这一点,但我缺少一些东西来实现它......
  • 更新了上面的答案。简而言之:将覆盖设为私有并提供新功能。但请注意,这是丑陋的设计。
【解决方案2】:

您有一个设计问题class1::method2(class1&amp;) const 必须适用于与帐单匹配的任何 参数,即对类型class1 的每个引用。如果class2 只能为class2 类型的参数实现method2(),那么它不仅在语法上而且在逻辑上都是不完整的:它无法处理预期用途

class2 A;
class1*B = method_returning_pter_to_class1_object();
A.method2(*B);                         // intended usage of virtual function

(如果您不打算使用这种类型的用法,那么您在class1 中的设计存在缺陷。)

当然,如果参数实际上是 class2&amp; 类型,您可以使用 dynamic_cast 来调用特殊行为,即

void class2::method(class1&x) const
{
  class2*x2 = dynamic_cast<class2*>(&x);
  if(x2)
    apply_method_taking_class2(*x2);
  else
    apply_method_for_other_than_class2_object(x);
}

但这可能会导致一些运行时损失。

【讨论】:

  • 这个想法是让 class1 和 void method1(class1& ) const; class2 with void method1(class2& ) const;类 3 无效方法 1(类 3& )常量;类 4 无效方法 1(类 4& )常量; .... classN with void method1(classN& ) const; - 其中 clas1 是接口类,而 class1、class2、class3、... classN 是实现此类接口的类。老实说,您的解决方案会编译文件,但我认为它不会很干净。您还有其他建议吗?
  • 这意味着你的设计有问题。首先考虑更好的设计。
猜你喜欢
  • 2017-12-10
  • 2012-07-23
  • 1970-01-01
  • 1970-01-01
  • 2016-07-04
  • 2012-09-18
  • 2016-08-22
  • 2021-12-07
  • 2013-11-15
相关资源
最近更新 更多