2017-01-12 87 views
0

我想设计一个C++ Template类,它将包含Tree(即appendChild,childCount)的所有功能。然后,我想从此模板类中获取extend,并设计具有现有功能的自定义树类(读为Methods)以及额外的功能。了解C++模板类继承

到目前为止,我得到了这个。现在

#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; 
} 

,如果我不尝试添加一些新的构造函数,派生类(即构造器overload),一切都很好。但是,如果我添加一个新的构造函数(如代码段所示),我无法访问(Base Template类的)现有构造函数。我收到以下错误在该行TreeItem *child2 = new TreeItem();

enter image description here

我在这里做一些愚蠢的事?我可以重载其他方法,只在构造函数失败。我如何重载基模板类的现有构造函数?

+1

你需要实现一个默认的构造函数,如果你有一个自定义的,只是把'TreeItem(){}'在'TreeItem'类。 – George

+0

只是一些建议 - 为什么用户必须提供一个指向你的'TreeTemplate'类的指针?如果我想在树内存储一个简单的'int',为什么我需要通过为所有我想存储的整数执行'new int'来冒内存泄漏的风险?一个好的类可以处理值类型 - 如果用户真的想存储指针,那么他们会给你的类指针来存储。例如,比较'std :: vector '和'std :: vector '。如果我想要存储指向Widget的指针,我声明后者。 – PaulMcKenzie

+0

@George,那么,只要我在派生类中声明了一个新的构造函数,我就无法访问基类的构造函数? –

回答

0

有两个问题需要解决。首先,当你为一个类型定义一个构造函数时,该类型的默认构造函数不会被隐式生成。你可以强制使用= default。这是一个例子。

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

第二个问题是派生类型不继承它的父类的构造函数。直观地说,在以下示例中,Base类型的构造函数如何构造Derived类型的实例? 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); 
} 

类型的构造函数你实际上构建符合条件,没有它的基本类型的构造函数。为了模拟行为,你必须为你想要支持的一组参数提供新的构造函数。

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; 
}; 

某些箱子您可以通过提供一个可变参数模板的构造类似于下面的示例解决此问题。只有在有特殊需要的情况下才能做到这一点。

#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); 
}