Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有多个“级别”派生的抽象类 我在C++中有一个问题,我有< /P> 一个具有公共成员和纯虚函数的抽象基类。这是下面代码中的一个示例。 具有不同成员和函数的多个派生类。这是下面代码中的B和C。 实现虚拟函数且没有新成员的多个派生类。这是下面代码中的do_stuff_1和do_stuff_2。_C++_Templates_Inheritance_Abstract Class - Fatal编程技术网

具有多个“级别”派生的抽象类 我在C++中有一个问题,我有< /P> 一个具有公共成员和纯虚函数的抽象基类。这是下面代码中的一个示例。 具有不同成员和函数的多个派生类。这是下面代码中的B和C。 实现虚拟函数且没有新成员的多个派生类。这是下面代码中的do_stuff_1和do_stuff_2。

具有多个“级别”派生的抽象类 我在C++中有一个问题,我有< /P> 一个具有公共成员和纯虚函数的抽象基类。这是下面代码中的一个示例。 具有不同成员和函数的多个派生类。这是下面代码中的B和C。 实现虚拟函数且没有新成员的多个派生类。这是下面代码中的do_stuff_1和do_stuff_2。,c++,templates,inheritance,abstract-class,C++,Templates,Inheritance,Abstract Class,到目前为止,我的解决方案是混合使用模板和抽象类。目标是保持一个指向抽象类B orC的指针,并调用do_stuff。我的问题是 我的解决方案好吗? 如果没有,是否有更好的解决方案? 如果是这样,我是否应该注意一些陷阱? 到目前为止,这是我的解决方案 包括 包括 /*基虚拟类*/ 甲级{ 公众: INTA; a:aa{} 虚空do_stuff=0; }; /*do_stuf的具体实现*/ 样板 第1类:公共事务{ 公众: 使用T::T; 虚度光阴{ std::cout您的解决方案看起来不错。这是一种

到目前为止,我的解决方案是混合使用模板和抽象类。目标是保持一个指向抽象类B orC的指针,并调用do_stuff。我的问题是

我的解决方案好吗? 如果没有,是否有更好的解决方案? 如果是这样,我是否应该注意一些陷阱? 到目前为止,这是我的解决方案

包括 包括 /*基虚拟类*/ 甲级{ 公众: INTA; a:aa{} 虚空do_stuff=0; }; /*do_stuf的具体实现*/ 样板 第1类:公共事务{ 公众: 使用T::T; 虚度光阴{
std::cout您的解决方案看起来不错。这是一种编译时方法,您可以创建4个不同的对象

主要缺点是:

除非实例化模板,否则您将不知道do_stuff代码是否正确。 您可以使用非基类A的类实例化do_stuff_1或do_stuff_2。您至少应该在模板中使用override,以确保它重写虚拟函数。 以下是解决这些问题的一个小改进:

template<class T>
class do_stuff_2 : public T {
public:
  using T::T;

  void do_stuff() override {
    static_assert (std::is_base_of<A, T>::value, "T should be derived from A");
    std::cout << "do_stuff_2 " << this->a + 1 << std::endl;
  }
};

顺便说一句,使用make_unique会很好。

对我来说,这看起来像某种策略,可能看起来像:

#include <iostream>
#include <memory>
#include <type_traits>

struct AwayToDoTheStuff {
    virtual void operator()(int a) = 0;

    virtual ~AwayToDoTheStuff() {}
};

/* concrete implementations of do_stuf */
class HowToDoStuff1 : public AwayToDoTheStuff {
    public:
        void operator()(int a) override {
            std::cout << "do_stuff_1 " << a << std::endl;
        }
};

class HowToDoStuff2 : public AwayToDoTheStuff {
    public:
        void operator()(int a) override {
            std::cout << "do_stuff_2 " << a + 1 << std::endl;
        }
};

/* base virtual class */
template <class HowToDoStuff>
class A {
    public:
        int a;

        A(int a) : a(a) {}

        void do_stuff() {
            static_assert(std::is_base_of<AwayToDoTheStuff, HowToDoStuff>::value);
            HowToDoStuff()(a);
        }
};

/* derived classes from A */
template <class HowToDoStuff>
class B : public A<HowToDoStuff> {
    public:
        int b;         // one member here but many more in my application

        B(int a, int b): A<HowToDoStuff>(a), b(b) {}
};

template <class HowToDoStuff>
class C : public A<HowToDoStuff> {
    public:
        std::string c; // one member here but many more in my application

        C(int a, std::string c): A<HowToDoStuff>(a), c(c) {}
};

int main() {
    B<HowToDoStuff1>(1, 1).do_stuff();
    B<HowToDoStuff2>(1, 2).do_stuff();

    C<HowToDoStuff1>(1, "Yo").do_stuff();
    C<HowToDoStuff2>(1, "Hello").do_stuff();

    return 0;
}
这样就可以在不透明的对象上调用do_

您还可以在创建时传递HowToDoStuff对象:

/* base virtual class */
class A {
    std::unique_ptr<AwayToDoTheStuff> _stuffer;
    public:
        int a;

        A(std::unique_ptr<AwayToDoTheStuff> stuffer, int a) : _stuffer(std::move(stuffer)), a(a) {}

        void do_stuff() {
            (*_stuffer)(a);
        }
};

/* derived classes from A */
class B : public A {
    public:
        int b;         // one member here but many more in my application

        B(std::unique_ptr<AwayToDoTheStuff> &stuffer, int a, int b): A(std::move(stuffer), a), b(b) {}
};

class C : public A {
    public:
        std::string c; // one member here but many more in my application

        C(std::unique_ptr<AwayToDoTheStuff> &stuffer, int a, std::string c): A(std::move(stuffer), a), c(c) {}
};

int main() {

    auto stuffer1forB = std::unique_ptr<AwayToDoTheStuff>(new HowToDoStuff1);
    auto stuffer2forB = std::unique_ptr<AwayToDoTheStuff>(new HowToDoStuff2);

    B(stuffer1forB, 1, 1).do_stuff();
    B(stuffer2forB, 1, 2).do_stuff();

    auto stuffer1forC = std::unique_ptr<AwayToDoTheStuff>(new HowToDoStuff1);
    auto stuffer2forC = std::unique_ptr<AwayToDoTheStuff>(new HowToDoStuff2);

    C(stuffer1forC, 1, "Yo").do_stuff();
    C(stuffer2forC, 1, "Hello").do_stuff();

    return 0;
}

这个解决方案的一个问题是,我不能创建指向类B或C的指针。例如,我不能拥有像void fB&B这样的函数。因此,我无法实现以下目标:u目标是持有指向抽象类的指针…u如果我没有弄错的话。我不确定我是否理解你的观点;我在这里删除了唯一的_ptr,因为我认为它们不是essential表示类的层次结构,但如果愿意,您仍然可以创建指向B和C的指针。它们是模板,因此我需要有模板函数或多个函数,并带有参数,例如void fB&B和void fB&B。我可能错了。
/* base virtual class */
class A {
    public:
        void do_stuff() = 0;
};

template <class HowToDoStuff>
class Policy_A : public A {
    public:
        int a;

        A(int a) : a(a) {}

        void do_stuff() override {
            static_assert(std::is_base_of<AwayToDoTheStuff, HowToDoStuff>::value);
            HowToDoStuff()(a);
        }
};

/* derived classes from A */
template <class HowToDoStuff>
class B : public Policy_A<HowToDoStuff> {
    public:
        int b;         // one member here but many more in my application

        B(int a, int b): Policy_A<HowToDoStuff>(a), b(b) {}
};

template <class HowToDoStuff>
class C : public Policy_A<HowToDoStuff> {
    public:
        std::string c; // one member here but many more in my application

        C(int a, std::string c): Policy_A<HowToDoStuff>(a), c(c) {}
};
/* base virtual class */
class A {
    std::unique_ptr<AwayToDoTheStuff> _stuffer;
    public:
        int a;

        A(std::unique_ptr<AwayToDoTheStuff> stuffer, int a) : _stuffer(std::move(stuffer)), a(a) {}

        void do_stuff() {
            (*_stuffer)(a);
        }
};

/* derived classes from A */
class B : public A {
    public:
        int b;         // one member here but many more in my application

        B(std::unique_ptr<AwayToDoTheStuff> &stuffer, int a, int b): A(std::move(stuffer), a), b(b) {}
};

class C : public A {
    public:
        std::string c; // one member here but many more in my application

        C(std::unique_ptr<AwayToDoTheStuff> &stuffer, int a, std::string c): A(std::move(stuffer), a), c(c) {}
};

int main() {

    auto stuffer1forB = std::unique_ptr<AwayToDoTheStuff>(new HowToDoStuff1);
    auto stuffer2forB = std::unique_ptr<AwayToDoTheStuff>(new HowToDoStuff2);

    B(stuffer1forB, 1, 1).do_stuff();
    B(stuffer2forB, 1, 2).do_stuff();

    auto stuffer1forC = std::unique_ptr<AwayToDoTheStuff>(new HowToDoStuff1);
    auto stuffer2forC = std::unique_ptr<AwayToDoTheStuff>(new HowToDoStuff2);

    C(stuffer1forC, 1, "Yo").do_stuff();
    C(stuffer2forC, 1, "Hello").do_stuff();

    return 0;
}