具有非共享方法的虚函数

Virtual function with non-shared method

我正在进行个人项目,我需要做一些不寻常的事情。我的代码有点长,但问题出在结构上,所以我将使用一个非常简化的问题版本。

问题是我需要能够在克隆后使用B的方法(在本例中为moo),它在A中不存在。我试图使我的方法是虚拟的,但它不能解决问题。如果没有 CRTP,有什么办法可以做到这一点吗?

我真的不想使用 CRTP,因为它真的很复杂。 (在我的真实代码中,我有 4 个 class 继承链,所有 4 个都已经模板化了)

#include <iostream>

class A
{
    public:

        /*Common function*/
        virtual void foo(){
            std::cout << "call from A" << std::endl;
        }

        A* clone(){
            /*
            ...
            ...   Code I don't want to write again for B
            ...
            */
            return this;
        }

};

class B: public A
{

        
    public:

        /*Common function*/
        virtual void foo(){
            std::cout << "call from B" << std::endl;
        }

        /*Not derived from A*/
        void moo(){ //Doesn't work even with virtual keyword
            std::cout << "only exist in B" << std::endl;
        }
};


int main(int argc, char const *argv[])
{
    auto tB = new B();

    tB->foo();
    tB->moo();
    tB->clone()->foo();
    tB->clone()->moo();


    return 0;
}

编译器:

error: 'class A' has no member named 'moo'; did you mean 'foo'?
   38 |     tB->clone()->moo();
      |                  ^~~
      |                  foo

我不是英语,如果不清楚,请见谅。

好吧,根据评论、我的研究以及我认为 c++ 的工作方式,我放弃了寻找看起来像虚方法但仍然令人满意的东西。

所以我决定使用 CRTP,对于那些感兴趣的人,这里是我的模型 3(我删除了一个)的代码继承了 class CRTP,带有一个额外的类型模板参数:)

#include <iostream>

//CRTPI = "CRTP Interface", used for inheritances between CRTPs

template<typename Derived, typename T>
class CRTPI_A
{
    protected:
        T x = 0;


    public:

        T getX(){
            return x;
        }

        Derived* clone(){
            /*
            ...
            ...   Code I don't want to write again for B and it's childs
            ...
            */
            return new Derived();
        }

};

template<typename Derived, typename T>
class CRTPI_B: public CRTPI_A<Derived, T>
{
    public:

        //Only for B and its childs
        void iwd(){
            std::cout << "Hi, i'm a B child !" << std::endl;
        }


};

template<typename Derived, typename T>
class CRTPI_C: public CRTPI_B<Derived, T>{};

template<typename T>
class A: public CRTPI_A<A<T>, T>
{
    public:

        A(){};

        A(T z){
            this->x = z;
        }

        void foo(){
            std::cout << "call from A" << std::endl;
        }
};

template<typename T>
class B: public CRTPI_B<B<T>, T>
{

        
    public:

        B(){};

        B(T z){
            this->x = z;
        }

        void foo(){
            std::cout << "call from B" << std::endl;
        }

        //Not in CRTP interface so won't be inherited by C
        void UwU(){
            std::cout << "I'm exclusive to B" << std::endl;
        }

};

template<typename T>
class C: public CRTPI_C<C<T>, T>
{
    public:

        C(){};

        C(T z){
            this->x = z;
        };

        void foo(){
            std::cout << "call from C" << std::endl;
        }
};


int main(int argc, char const *argv[])
{
    auto tA = new A<char>('A');
    auto tB = new B<int>(2);
    auto tC = new C<float>(420.69);


    tA->foo();
    tA->clone()->foo();

    printf("\n");

    tB->foo();
    tB->iwd();
    tB->clone()->foo();
    tB->clone()->iwd();

    tB->UwU();

    printf("\n");

    tC->foo();
    tC->iwd();
    // tC->UwU(); //Won't work but that's planned

    std::cout << "\n" << tA->getX() << ":" << tB->getX() <<":" << tC->getX() << std::endl;


    return 0;
}

注意,这里 C 的 CRTP 接口是可选的,因为它没有子 class 也没有独占方法,所以我们可以只写:

template<typename T>
class C: CRTPI_B<C<T>, T>
{
    ...
}