【问题标题】:clang++ : Cannot allocate an object of abstract typeclang++:无法分配抽象类型的对象
【发布时间】:2014-01-07 01:00:44
【问题描述】:

我有“无法分配抽象类型的对象”错误。

当我创建一个对象Be(继承自抽象类Ae)并将它传递给采用const Ae& 的方法时,我得到了它。我认为作为参考传递时应该不是问题。错误说:error: allocating an object of abstract class type Be

程序的逻辑如下:

//A.hpp
struct A : public std::exception { //Exception class
    class Ae { //Error message class
        virtual const char* message() const = 0;
        inline operator const char*() const {
            return message();
        }
    };
    // fields describing where the error occurred in file input
    int a, b, c, d;
    // string reporting what happened
    const char* msg;
    A( const Ae& e, int a, int b, int c, int d ) : a(a), b(b), c(c), d(d), msg(e)
    {}
    const char* what() const throw() { /* printing some nice report */ }
    ~A() throw () {}
};

//B.hpp 
struct B : public A {
    B( const Ae& e, int a, int b, int c, int d ) : A( e,a,b,c,d )
    {}
    struct Be : public Ae { //particular error having relevant class name e.g. IncorrectInput
        const char* message() const {
            return "Some error description";
        }
    }; // more of alikes
};

//AUser.hpp
struct AUser { // some module that will be throwing A
    int a, b, c, d;
    A Exception( const Ae& e ) {
        return A( e, a, b, c, d );
    }
};

//BUser.hpp
struct BUser : public AUser {
    void fun() { // any method
        // (...) does sth
        if ( goeswrong )
            throw Exception( B::Be() );
    }
};

我的代码有什么问题?

为了阐明此类结构的目标 - AUser 是 CsvFile,BUser 是 ParticularCsvFile(使用方法识别哪个字段包含哪种数据类型),A 是 CsvFileExceotion,B 是 ParticularFileException,Ae 是 ErrorCode,Be 是例如 ErrorWhenReadingPricesCell

包含throw Exception( B::Be() ); 的行弹出错误,另外声明note: unimplemented pure virtual method 'message' in 'Be' public: virtual const char* message() const = 0;

编辑

根据要求,exact g++ -Wall -pedantic -Wextra 如下所示。 请注意,我简化了上面的代码并更改了名称: BUser == DividendsFile, B == DividendsFileReadingException, Be == UnexpectedStockDividend, AUser == CsvFile, A == CsvFileReadingException, Be == ErrorCode

quotreader2.cpp:18:5: warning: unused parameter ‘argc’ [-Wunused-parameter]
Input/DividendsFile.cpp: In member function ‘int DividendsFile::getStockDividend()’:
Input/DividendsFile.cpp:28:85: error: cannot allocate an object of abstract type ‘DividendsFileReadingException::UnexpectedStockDividend’
In file included from Input/DividendsFile.cpp:3:0:
Input/Exceptions/DividendsFileReadingException.hpp:28:12: note:   because the following virtual functions are pure within ‘DividendsFileReadingException::UnexpectedStockDividend’:
In file included from Input/CsvFile.hpp:4:0,
                 from Input/DividendsFile.hpp:4,
                 from Input/DividendsFile.cpp:2:
Input/Exceptions/CsvFileReadingException.hpp:17:37: note:   virtual const char* CsvFileReadingException::ErrorCode::message() const
make: *** [bin/test.bin] Error 1

【问题讨论】:

  • 哪一行是错误(我看过一次,没看出来)
  • @AlecTeal 我更新了该信息的问题。见底部。
  • Be中的virtual关键字忘记了吗?
  • 你不能只在代码中添加 :public Ae 而不更新你得到的错误,你现在太残忍了
  • 我怀疑 OP 在代码中有错字,他忘记在此处转录了...(但添加新的:/)

标签: c++ inheritance abstract-class virtual-functions


【解决方案1】:

修复了几个拼写错误的语法错误,例如从

class Ae

struct Ae

,

来自

struct Be

struct Be : public Ae

来自

A Exception( const Ae& e )

A Exception( const A::Ae& e )

代码在 clang 中完美编译,所以我不明白你的问题。您是否至少尝试编译您在此问题中发布的代码?

【讨论】:

  • OP 撒了谎,他确实忘记了公众 Ae.....stackoverflow.com/questions/20962173/…
  • 我的程序要大得多。我在这里发布了相关的摘要。我的程序无法编译,我的代码中也没有伪造 public ae,我为什么要撒谎?如果编译成功,则意味着问题出在不同的代码中,而 g++ 在于问题的根源(不是第一次)。而且我不能在这里发布整个代码,因为它太大了......
  • 没有人怀疑你的问题。然后,您将尝试制作一个无法编译的最小示例。如果您的问题没有问题,人们将无法提供帮助。
【解决方案2】:

哦,这很明显!

由于某种原因异常是一个返回A的函数

这里:

A Exception( const Ae& e ) {
    return A( e, a, b, c, d );
}

AAAAnnnnd

struct A : public std::exception { //Exception class
    class Ae { //Error message class
        virtual const char* message() const = 0;

我们这里有一个虚方法。

然后

            throw Exception( B::Be() );

意思是“抛出一个产生异常函数调用的A”

但你不能扔 A!因为A是抽象的

另外

异常需要 Ae,但你给它一个 Be,两者之间没有转换。

编译器实际上在这里发现了 4 个错误,这就是报告如此无用的原因(我将向 GCC 邮件列表提出为什么它如此无用的问题)

Be 不继承任何东西

struct Be { //particular error having relevant class name e.g. IncorrectInput
    const char* message() const {
        return "Some error description";
    }
}; // more of alikes

【讨论】:

  • 为什么是摘要? Ae 是抽象的。
  • Be 继承自 Ae,所以有转换。
  • 这有很多问题,说真的,很难阅读,我不知道你在做什么,这里有一些提示,但你也很困惑编译器。
  • 哦,它确实继承了,忘记写了:/顺便说一句,我应该更改名称还是什么?
  • 重新开始,说真的,这读起来很糟糕,如果你要使用 camelCase - 我喜欢顺便说一句,使用 CamelCase 作为类型名(类)和 camelCase 作为方法,这就是我假设的原因Exception 是一种类型。 @infoholic_anonymous
【解决方案3】:

看来您实际上并没有在类 B 中实现类 A 中声明的某些抽象方法。如果存在未实现的抽象方法,则类本身 (B) 仍然是抽象的。尝试创建抽象类的新实例是一个编译错误(因为如果编译器调用了那个未实现的方法,它不知道该怎么做)。检查A中声明的所有抽象方法是否都在B中实现,你应该没问题...

进一步纠正你的错误:

struct Be { //particular error having relevant class name e.g. IncorrectInput
        const char* message() const {
            return "Some error description";
        }
    }; 

class Ae 已经声明 message() 是虚拟的... Class B 没有实现这个虚拟方法,struct Be 是。 struct Be 是 B 的一部分,它本身并不扩展 Ae。因此,该方法未作为 B 的一部分实现...不知道为什么会被否决...

【讨论】:

  • 但是B::Be 表示一个完整的类型。它不需要B 存在,如果你说的是真的,我们应该得到一个 linker 错误。到未定义的 vtable,如果在编译期间无法去虚拟化,则运行时崩溃。
  • 你没有在B中实现,你放在Be里面
  • Class BeA 没有任何关系,只是在它的命名空间中(类是具有结构的命名空间)。再一次,假设你只有头文件,链接是 LINKERS 的工作,而不是编译东西,你可以在不声明虚拟的文件中使用它,但链接器会发牢骚!
  • 所以我在这里也犯了一个语义错误。它是 Ae 类,而不是 A 声明虚拟方法......你如何定义 Be 正在扩展 Ae ?这就是我想要解决的问题。看起来你只是在声明 B 有一个新的内部类型 Be。对我来说没有任何迹象表明 Be 扩展了 Ae 并因此实现了它的消息功能。 B 有两个内部类型,Ae 和 Be,在继承方面不相关。
  • 问题中的代码有很多错误(请参阅我的回答,我真的很讨厌这个问题),但是您的回答没有任何意义,当然您可以使用摘要的特征班级!无论如何,我现在要离开这个问题,因为代码太复杂了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多