【问题标题】:Yet another abstract class issue in C++ with closuresC++ 中另一个带有闭包的抽象类问题
【发布时间】:2013-06-09 22:51:00
【问题描述】:

我在使用 g++ -std=c++11 参数编译此代码时遇到问题:

#include <iostream>
#include <unordered_map>
#include <functional>
#include <iostream>
using namespace std;;

template <typename T> class opt {
    public:
        opt() {};
        ~opt() {};
        virtual int isEmpty() = 0;
        virtual T getObject() = 0;
};

template <typename T> class oopt : public opt<T> {
    private:
        T ret;
    public:
        oopt(T obj) { ret = obj; };
        ~oopt() override;
        int isEmpty() { return 0; };
        T getObject() { return ret; };
};
int main(void) {

    function<opt<int>(int)> fu = [](int j) { return (oopt<int>(10)); };

    return 1;
}

此代码返回以下错误:

assoc_array.cc: In instantiation of ‘class oopt<int>’:
assoc_array.cc:68:63:   required from here
assoc_array.cc:29:3: error: ‘oopt<T>::~oopt() [with T = int]’ marked override, but does not override
In file included from assoc_array.cc:3:0:
/usr/include/c++/4.7/functional: In instantiation of ‘static _Res std::_Function_handler<_Res(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Res = opt<int>; _Functor = main()::<lambda(int)>; _ArgTypes = {int}]’:
/usr/include/c++/4.7/functional:2298:6:   required from ‘std::function<_Res(_ArgTypes ...)>::function(_Functor, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type) [with _Functor = main()::<lambda(int)>; _Res = opt<int>; _ArgTypes = {int}; typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type = std::function<opt<int>(int)>::_Useless]’
assoc_array.cc:68:67:   required from here
/usr/include/c++/4.7/functional:1909:7: error: invalid abstract return type for function ‘static _Res std::_Function_handler<_Res(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Res = opt<int>; _Functor = main()::<lambda(int)>; _ArgTypes = {int}]’
assoc_array.cc:7:29: note:   because the following virtual functions are pure within ‘opt<int>’:
assoc_array.cc:11:15: note:     int opt<T>::isEmpty() [with T = int]
assoc_array.cc:12:13: note:     T opt<T>::getObject() [with T = int]
In file included from assoc_array.cc:3:0:
/usr/include/c++/4.7/functional:1912:40: error: cannot allocate an object of abstract type ‘opt<int>’
assoc_array.cc:7:29: note:   since type ‘opt<int>’ has pure virtual functions
In file included from assoc_array.cc:3:0:
/usr/include/c++/4.7/functional:1743:2: error: ‘static _Functor* std::_Function_base::_Base_manager<_Functor>::_M_get_pointer(const std::_Any_data&) [with _Functor = main()::<lambda(int)>]’, declared using local type ‘main()::<lambda(int)>’, is used but never defined [-fpermissive]

使用带有静态转换到接口的闭包我的错误在哪里?我已经阅读过类似的回复(C++ and inheritance in abstract classesC++ - "Member function not declared" in derived class),但如果我删除闭包定义,编译时似乎不会出错。提前致谢。

编辑

即使使用以下代码:

#include <iostream>
#include <unordered_map>
#include <functional>
#include <iostream>
using namespace std;;

template <typename T> class opt {
    public:
        opt<T>(T) {};
        ~opt<T>() {};
        virtual int isEmpty() = 0;
        virtual T getObject() = 0;
};

template <typename T> class oopt : public opt<T> {
    private:
        T ret;
    public:
        oopt<T>(T obj) { ret = obj; };
        ~oopt<T>() override;
        int isEmpty() { return 0; };
        T getObject() { return ret; };
};
int main(void) {

    function<opt<int>(int)> fu = [](int j) { return (oopt<int>(10)); };

    return 1;
}

我还有以下编译问题:

assoc_array.cc: In instantiation of ‘class oopt<int>’:
assoc_array.cc:26:64:   required from here
assoc_array.cc:20:4: error: ‘oopt<T>::~oopt() [with T = int]’ marked override, but does not override
assoc_array.cc: In instantiation of ‘oopt<T>::oopt(T) [with T = int]’:
assoc_array.cc:26:64:   required from here
assoc_array.cc:19:19: error: no matching function for call to ‘opt<int>::opt()’
assoc_array.cc:19:19: note: candidates are:
assoc_array.cc:9:4: note: opt<T>::opt(T) [with T = int]
assoc_array.cc:9:4: note:   candidate expects 1 argument, 0 provided
assoc_array.cc:7:30: note: constexpr opt<int>::opt(const opt<int>&)
assoc_array.cc:7:30: note:   candidate expects 1 argument, 0 provided
In file included from assoc_array.cc:3:0:
/usr/include/c++/4.7/functional: In instantiation of ‘static _Res std::_Function_handler<_Res(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Res = opt<int>; _Functor = main()::<lambda(int)>; _ArgTypes = {int}]’:
/usr/include/c++/4.7/functional:2298:6:   required from ‘std::function<_Res(_ArgTypes ...)>::function(_Functor, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type) [with _Functor = main()::<lambda(int)>; _Res = opt<int>; _ArgTypes = {int}; typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type = std::function<opt<int>(int)>::_Useless]’
assoc_array.cc:26:68:   required from here
/usr/include/c++/4.7/functional:1909:7: error: invalid abstract return type for function ‘static _Res std::_Function_handler<_Res(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Res = opt<int>; _Functor = main()::<lambda(int)>; _ArgTypes = {int}]’
assoc_array.cc:7:30: note:   because the following virtual functions are pure within ‘opt<int>’:
assoc_array.cc:11:16: note:     int opt<T>::isEmpty() [with T = int]
assoc_array.cc:12:14: note:     T opt<T>::getObject() [with T = int]
In file included from assoc_array.cc:3:0:
/usr/include/c++/4.7/functional:1912:40: error: cannot allocate an object of abstract type ‘opt<int>’
assoc_array.cc:7:30: note:   since type ‘opt<int>’ has pure virtual functions
In file included from assoc_array.cc:3:0:
/usr/include/c++/4.7/functional:1743:2: error: ‘static _Functor* std::_Function_base::_Base_manager<_Functor>::_M_get_pointer(const std::_Any_data&) [with _Functor = main()::<lambda(int)>]’, declared using local type ‘main()::<lambda(int)>’, is used but never defined [-fpermissive]

【问题讨论】:

  • 看起来你甚至没有在 main 中使用 eopt,只是为了我们的缘故摆脱它
  • eopt 用于对所描述的错误不感兴趣的代码的某些部分。
  • 当您在 SO 上发帖时,让代码尽可能简单符合每个人的最大利益
  • 好的,完成。我已经用代码更正编辑了上面的帖子。

标签: c++ c++11 closures lambda class-hierarchy


【解决方案1】:

因为 gcc 是周围的标准编译器,他的错误不是最清楚的,甚至 C++ 比 C 更严重,所以我通常用 clang 和 gcc 编译所有东西以确保。 用clang编译: 我有这个与 aaronman 代码,t

clang++ -std=c++11 test.cc                                                                                                                                                                              ~
test.cc:20:20: error: only virtual member functions can be marked 'override'
        ~oopt<T>() override;
                   ^~~~~~~~
test.cc:26:54: note: in instantiation of template class 'oopt<int>' requested here
    function<opt<int>(int)> fu = [](int j) { return (oopt<int>(10)); };
                                                     ^
test.cc:19:9: error: constructor for 'oopt<int>' must explicitly initialize the base class 'opt<int>' which does not have a default constructor
        oopt<T>(T obj) { ret = obj; };
        ^
test.cc:26:54: note: in instantiation of member function 'oopt<int>::oopt' requested here
    function<opt<int>(int)> fu = [](int j) { return (oopt<int>(10)); };
                                                     ^
test.cc:7:29: note: 'opt<int>' declared here
template <typename T> class opt {
                            ^
2 errors generated.

这是你的第一个:

clang++ -std=c++11 test2.cc                                                                                                                                                                             ~
test2.cc:20:17: error: only virtual member functions can be marked 'override'
        ~oopt() override;
                ^~~~~~~~
test2.cc:26:54: note: in instantiation of template class 'oopt<int>' requested here
    function<opt<int>(int)> fu = [](int j) { return (oopt<int>(10)); };
                                                     ^
1 error generated.

在修复这些错误后,clang 在链接期间给了我这个:

clang++ -o -std=c++11 test2.o -Wall -Werror                                                                                                                                                             ~
test2.o: In function `std::_Function_handler<opt<int> (int), main::$_0>::_M_invoke(std::_Any_data const&, int)':
test2.cc:(.text+0x1a7): undefined reference to `oopt<int>::~oopt()'
test2.o:(.rodata._ZTV4ooptIiE[_ZTV4ooptIiE]+0x10): undefined reference to `oopt<int>::~oopt()'
test2.o:(.rodata._ZTV4ooptIiE[_ZTV4ooptIiE]+0x18): undefined reference to `oopt<int>::~oopt()'
clang: error: linker command failed with exit code 1 (use -v to see invocati

开)

这不是一个准确的答案,但这可能会有很大帮助

【讨论】:

  • 谢谢:主要问题是有些东西是用g++编译的,而不是clang++编译的。顺便说一句,我实际上正在研究解决方案......
【解决方案2】:

好的,首先摆脱覆盖并将析构函数设为虚拟(在继承时它们应该始终是)。析构函数也未在基类中实现

#include <iostream>
#include <unordered_map>
#include <functional>
#include <iostream>
using namespace std;;

template <typename T> class opt {
    public:
        opt() {};
        virtual ~opt() {};
        virtual int isEmpty() = 0;
        virtual T getObject() = 0;
};

template <typename T> class oopt : public opt<T> {
    private:
        T ret;
    public:
        oopt(T obj) { ret = obj; };
        ~oopt(){};
        int isEmpty() { return 0; };
        T getObject() { return ret; };
};
int main(void) {

    function<opt<int>(int)> fu = [](int j) { return (oopt<int>(10)); };

    return 1;
}

现在编译。至于你最初得到的错误,我不能说它们来自哪里,因为我没有得到它们

【讨论】:

  • 好吧,在 oopt 定义中我声明:oopt(T obj) { ret = obj; }; 所以,对于T = int,我有一个 int 构造函数:所以即使对于超类,我也必须按如下方式实现它?
  • 那是 oopt 而不是 opt,老实说这很难阅读考虑给你的类提供更多描述性的名称或缩短代码以将其放在 SO
  • 好吧,鉴于你的代码,我仍然有以下错误:pastebin.com/BphD63pu
  • 要么你没有使用 c++11,要么你包含了一些你没有向我展示的东西
  • 好吧,我只是用g++ -std=c++11 -c assoc_array.cc 编译,并且只使用您发布的代码。我真的不知道该说什么。我在两台不同的计算机上遇到相同的错误。
【解决方案3】:

好吧,希望我的解决方案是正确的:至少它可以编译:)。我将把它作为答案,以便接收有关该解决方案的其他 cmets。再次感谢。

#include <iostream>
#include <unordered_map>
#include <functional>
#include <iostream>
#include <memory>

using namespace std;

//I need shared_pointers in order to gain the C++ dynamic casting
template <typename T> class Ptr {
    shared_ptr<T> ptr;

    public:
        Ptr(T* obj) : ptr{obj} {};
        Ptr(shared_ptr<T> obj) : ptr{obj} {};

        ~Ptr() {  };

        template <typename U> Ptr<U> Cast();

        T* operator->() const  {return &(*this->ptr);}
        operator T() const { return (*this->ptr); };

};

template <typename T> template <typename U> Ptr<U> Ptr<T>::Cast(){
    return Ptr<U>{dynamic_pointer_cast<U>(ptr)};
};


template <typename T> class opt {
    protected:
        T ret;                
    public:
       ~opt() {};
       virtual int isEmpty() = 0;
       virtual T* getObject() = 0;
       operator T() const { return ret; }; 
};

template <typename T> class oopt : public opt<T> {
    public:
    oopt(T obj) { 
        this->ret = obj; 
    };  
    int isEmpty() { return 1; };
    T* getObject() { return &this->ret; }
};

template <typename T> class eopt : public opt<T> {
    public:
    eopt() { };  //for downcasting matters
    T* getObject() { return nullptr; } //
    int isEmpty() { return 1; };
};

int main(void) {

    Ptr<oopt<int>> u(new oopt<int>(500));
    Ptr<opt<int>> w = u.Cast<opt<int>>();
    cout << (*(w->getObject())) << "\n" ;

    Ptr<opt<int>> none(new eopt<int>());
    w = none.Cast<opt<int>>();
    if ((w->getObject()) == nullptr) {
        cout << "null" << "\n";
    }

    return 1;

}

【讨论】:

    猜你喜欢
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 2019-09-14
    • 1970-01-01
    相关资源
    最近更新 更多