C++ 为什么是C++;继承代码示例的行为如下

C++ 为什么是C++;继承代码示例的行为如下,c++,inheritance,virtual,overriding,C++,Inheritance,Virtual,Overriding,我有一个行为奇怪的代码示例。 在C++中继承,可以声明指针的数组,它具有纯虚函数(AKA接口)和调用派生的成员函数;p> class Base { public: virtual void call() = 0; }; class Derived1 : public Base { public: void call() override final { std::wcout << L"derived 1" << std::en

我有一个行为奇怪的代码示例。 在C++中继承,可以声明指针的数组,它具有纯虚函数(AKA接口)和调用派生的成员函数;p>
class Base {

public:

    virtual void call() = 0;

};

class Derived1 : public Base {

public:

    void call() override final {

        std::wcout << L"derived 1" << std::endl;

    }

};

class Derived2 : public Base {

public:

    void call() override final {

        std::wcout << L"derived 2" << std::endl;

    }

};

int main() {

    Base* b[2];    

    b[0] = new Derived1;
    b[1] = new Derived2;

    for (int i = 0; i < 2; ++i) {

        b[i]->call();

    }

    return 0;

}
正如计划的那样。 但当我尝试以下代码示例时,它让我有点困惑:

class Base {

public:

    virtual Base* print() = 0;

    template<typename T>
    Base& operator<<(const T &_val) {

        std::wcout << L" d0 << " << _val;
        return *this;

    }

};

class Derived1 : public Base {

public:

    Derived1* print() override final {

        return this;

    }

    template<typename T>
    Derived1& operator<<(const T &_val) {

        std::wcout << L" d1 << " << _val;
        return *this;

    }

};

class Derived2 : public Base {

public:

    Derived2* print() override final {

        return this;

    }

    template<typename T>
    Derived2& operator<<(const T &_val) {

        std::wcout << L" d2 << " << _val;
        return *this;

    }

};

int main() {

    Base* b[2];

    b[0] = new Derived1;
    b[1] = new Derived2;

    for (int i = 0; i < 2; ++i) {

        std::wcout << typeid(*b[i]->print()).name();
        *b[i]->print() << 7 << 7;
        std::wcout << std::endl;

    }

    return 0;

}
类基{
公众:
虚拟基*print()=0;
模板

Base&operator你的
操作符你真的认为所有的垂直空格都增加了代码的可读性吗?“问题是它为什么会这样?”因为这就是你编程要做的。模板化的
operator@NeilButterworth这只是我喜欢的代码样式。在规则中没有发现任何关于这种代码格式的建议。@NeilButterworth与大多数程序员相比,我更喜欢垂直空格(尽管承认没有这么多)。尽管如此,它仍然可读。除非这样做,否则就不值得抱怨了。@NeilButterworth缩进都排成一行,垂直空格的使用也是一致的。实际上,我发现不必要地使用宽字符串会让人分心,因为我很少看到这种语法(因为宽字符串的可移植性不强,您通常应该更喜欢显式Unicode类型)是的。如果希望通过模板元编程的魔力来使用静态多态性,那么类层次结构就没有必要了。看起来是这样,但是在这个例子中我如何实现静态多态性呢?我需要一个派生类数组。你必须为每种支持的数据类型编写一个专门的实现……否则你将不得不要“混合”模板和类层次结构方法,请稍候,我将发布另一个示例。然后您将必须强制转换…等等,我将发布最后一个示例,我将用尽所有选项;)老实说,我从来没有使用过内置RTTI。通常,当我需要RTTI时,我只使用一个简单的虚拟类类型enum getter…这非常便宜,我从来没有需要更多。但是这里有很多关于RTTI的问答,只要搜索一下就可以了。
class Base {

public:

    virtual Base* print() = 0;

    template<typename T>
    Base& operator<<(const T &_val) {

        std::wcout << L" d0 << " << _val;
        return *this;

    }

};

class Derived1 : public Base {

public:

    Derived1* print() override final {

        return this;

    }

    template<typename T>
    Derived1& operator<<(const T &_val) {

        std::wcout << L" d1 << " << _val;
        return *this;

    }

};

class Derived2 : public Base {

public:

    Derived2* print() override final {

        return this;

    }

    template<typename T>
    Derived2& operator<<(const T &_val) {

        std::wcout << L" d2 << " << _val;
        return *this;

    }

};

int main() {

    Base* b[2];

    b[0] = new Derived1;
    b[1] = new Derived2;

    for (int i = 0; i < 2; ++i) {

        std::wcout << typeid(*b[i]->print()).name();
        *b[i]->print() << 7 << 7;
        std::wcout << std::endl;

    }

    return 0;

}
8Derived1 d0 << 7 d0 << 7
8Derived2 d0 << 7 d0 << 7
class Base {

public:

    virtual Base* print() = 0;

    virtual Base& operator<<( int _val ) = 0;

};

class Derived1 : public Base {

public:

    Derived1* print() override final {

        return this;

    }

    Base& operator<<( int _val ) override final {

        std::wcout << L" d1 << " << _val;
        return *this;

    }

};

class Derived2 : public Base {

public:

    Derived2* print() override final {

        return this;

    }

    Base& operator<<( int _val ) override final {

        std::wcout << L" d2 << " << _val;
        return *this;

    }

};

int main() {

    Base* b[2];

    b[0] = new Derived1;
    b[1] = new Derived2;

    for (int i = 0; i < 2; ++i) {

        std::wcout << typeid(*b[i]->print()).name();
        *b[i]->print() << 7 << 7;
        std::wcout << std::endl;

    }

    return 0;

}
#include <iostream>
#include <string>

class Base {

public:

    virtual Base* print() = 0;
    virtual const wchar_t* className() const = 0;

    template<typename T>
    Base& operator<<(const T &_val) {

        std::wcout << L" " << className() << L" << " << L" << " << _val;
        return *this;

    }

};

class Derived1 : public Base {

public:
    const wchar_t* className() const override final { return L"d1"; }

    Derived1* print() override final {

        return this;

    }

};

class Derived2 : public Base {

public:
    const wchar_t* className() const override final { return L"d2"; }

    Derived2* print() override final {

        return this;

    }

};

int main() {

    Base* b[2];

    b[0] = new Derived1;
    b[1] = new Derived2;

    for (int i = 0; i < 2; ++i) {

        std::wcout << typeid(*b[i]->print()).name();
        *b[i]->print() << 7 << 7;
        std::wcout << std::endl;

    }

    return 0;

}
#include <iostream>

class Derived1;
class Derived2;

class Base {

public:

    virtual Base* print() = 0;


};

class Derived1 : public Base {

public:

    Derived1* print() override final {

        return this;

    }

    template<typename T>
    Derived1& operator<<(const T &_val) {

        std::wcout << L" d1 << " << _val;
        return *this;

    }

};

class Derived2 : public Base {

public:

    Derived2* print() override final {

        return this;

    }

    template<typename T>
    Derived2& operator<<(const T &_val) {

        std::wcout << L" d2 << " << _val;
        return *this;

    }

};

template<typename T>
Base& operator<<( Base& _base, const T &_val) {

    if( typeid( _base ) == typeid( Derived1 ))
        return dynamic_cast<Derived1*>(&_base)->operator << (_val);
    else
        return dynamic_cast<Derived2*>(&_base)->operator << (_val);
}

int main() {

    Base* b[2];

    b[0] = new Derived1;
    b[1] = new Derived2;

    for (int i = 0; i < 2; ++i) {

        std::wcout << typeid(*b[i]->print()).name();
        *b[i]->print() << 7 << 7;
        std::wcout << std::endl;

    }

    return 0;

}