[英]Understanding inheritance on C++ template class
我正在尝试设计一个C ++ Template
类,它将包含Tree
所有功能(即appendChild
, childCount
)。 然后,我想从此模板类extend
,并设计具有现有功能(称为Methods
)以及其他功能的自定义Tree类。
到目前为止,我明白了。
#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;
}
现在,如果我不尝试在派生类中添加一些新的Constructor(即,contructor overload
),那么一切都很好。 但是,如果我添加一个新的构造函数(如代码段所示),那么我将无法访问(基本模板类的)现有构造函数。 我在TreeItem *child2 = new TreeItem();
行中遇到以下错误TreeItem *child2 = new TreeItem();
我在这里做蠢事吗? 我可以重载其他方法,仅在构造方法上失败。 如何重载基本模板类的现有构造函数?
有两个问题要解决。 第一个是,当您为类型定义构造函数时,该类型的默认构造函数不会隐式生成。 您可以使用= 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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.