简体   繁体   English

了解C ++模板类的继承

[英]Understanding inheritance on C++ template class

I am trying to design a C++ Template class which will contain all the features of a Tree (ie appendChild , childCount ). 我正在尝试设计一个C ++ Template类,它将包含Tree所有功能(即appendChildchildCount )。 I want to then extend from this template class and design custom Tree class with existing features (read as Methods ) as well as extra features. 然后,我想从此模板类extend ,并设计具有现有功能(称为Methods )以及其他功能的自定义Tree类。

So far I got this. 到目前为止,我明白了。

#include <iostream>
#include <list>

/* TREE TEMPLATE CLASS */
template <class T>
class TreeTemplate
{
    public:
        TreeTemplate();
        void appendChild(T*);
        int getChildCount();
    protected:
        std::list<T*> m_childList;
};

/* Constuctor */
template <class T>
TreeTemplate<T>::TreeTemplate(){}

template <class T>
void TreeTemplate<T>::appendChild(T* t)
{
    m_childList.push_back(t);
}

template <class T>
int TreeTemplate<T>::getChildCount()
{
    return m_childList.size();
}

/* CLASS INHERITTING TEMPLATE */
class TreeItem : public TreeTemplate<TreeItem>
{
    public:
        std::string getTestName();
        TreeItem(std::string, std::string);

    private:
        std::string m_testID;
        std::string m_testName;
};

TreeItem::TreeItem(std::string test_id, std::string test_name)
{
    m_testID = test_id;
    m_testName = test_name;
}

std::string TreeItem::getTestName()
{
    return m_testName;
}

/* MAIN FUNCTION */
int main()
{
    TreeItem *myTree = new TreeItem("9", "10");
    TreeItem *child1 = new TreeItem("9.1", "10.1");
    TreeItem *child2 = new TreeItem();

    std::cout << myTree->getTestName() << std::endl;

    myTree->appendChild(child1);
    std::cout << myTree->getChildCount() << std::endl;
    return 0;
}

Now, if I don't try to add some new Constructor in derived class (ie contructor overload ), everything is good. 现在,如果我不尝试在派生类中添加一些新的Constructor(即,contructor overload ),那么一切都很好。 But, if I am adding a new Constructor (as the code segment shows), I am failing to access the existing constructor (of Base Template class). 但是,如果我添加一个新的构造函数(如代码段所示),那么我将无法访问(基本模板类的)现有构造函数。 I am getting following error in the line TreeItem *child2 = new TreeItem(); 我在TreeItem *child2 = new TreeItem();行中遇到以下错误TreeItem *child2 = new TreeItem();

在此处输入图片说明

Am I doing something stupid here ? 我在这里做蠢事吗? I can overload other methods, only failing at Constructor. 我可以重载其他方法,仅在构造方法上失败。 How can I overload existing constructor of base template class? 如何重载基本模板类的现有构造函数?

There are two problems to address. 有两个问题要解决。 The first is that when you define a constructor for a type, that type's default constructor is not implicitly generated. 第一个是,当您为类型定义构造函数时,该类型的默认构造函数不会隐式生成。 You can force it to be by using = default . 您可以使用= default强制使用它。 Here is an example. 这是一个例子。

struct Foo {
    Foo() = default;    // Allows default construction
    Foo(int value) : m_value(value) {}
    int m_value;
};

The second problem is that a derived type does not inherit it's parent's class' constructors. 第二个问题是派生类型不继承其父类的构造函数。 Intuitively, in the following example, how can a constructor of type Base construct an instance of type Derived ? 直观地,在下面的示例中, Base类型的构造函数如何构造Derived类型的实例? Base is not aware of Derived 's members. Base不知道Derived的成员。

class Base {
public:
    Base(int x, int y) : m_x(x), m_y(y) {}
private:
    int m_x;
    int m_y;
};

class Derived : public Base {
public:
    Derived(int x, int y, int z) : Base(x, y), m_z(z) {}
private:
    int m_z;
};

void foo()
{
    // If we use Base's constructor, what is m_z?
    // Won't compile
    Derived bar(1, 2);
}

Only the constructors of the type you are actually constructing are eligible, not it's base types' constructors. 只有您实际正在构造的类型的构造函数才是合格的,而不是基本类型的构造函数。 To simulate the behavior you will have to provide new constructors for the set of parameters you want to support. 为了模拟行为,您将必须为要支持的参数集提供新的构造函数。

class Derived : public Base {
public:
    Derived(int x, int y, int z) : Base(x, y), m_z(z) {}
    Derived(int x, int y) : Base(x, y), m_z(0) {}
private:
    int m_z;
};

In certain cases you can work around this problem by supplying a variadic template constructor like the following example. 某些情况下,您可以通过提供一个可变参数模板构造器(如以下示例)来解决此问题。 This shouldn't be done in general, only when there is a particular need. 通常,仅在有特殊需要时才应该这样做。

#include <utility>

class Base {
public:
    Base(int x, int y) : m_x(x), m_y(y) {}
private:
    int m_x;
    int m_y;
};

class Derived : public Base {
public:
    template<class ... Args>
    Derived(Args&&... args) : Base(std::forward<Args>(args)...) {};
};

void foo()
{
    Derived b(1, 2);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM