簡體   English   中英

了解C ++模板類的繼承

[英]Understanding inheritance on C++ template class

我正在嘗試設計一個C ++ Template類,它將包含Tree所有功能(即appendChildchildCount )。 然后,我想從此模板類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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM