模板和类继承

时间:2014-06-13 13:47:50

标签: c++ class templates

以下代码无法生成我想要的内容。

#include <iostream>
#include <vector>
#include <cstdlib>

using namespace std;

template<typename T> class Parent;
template<typename T> class Child1;
template<typename T> class Child2;

template<typename T> T fcn_default(const Parent<T> &obj, const T &phit){
    return 3.2 + phit;
}
template<typename T> T fcn_mod1   (const Child1<T> &obj, const T &phit){
    return 1.2 + phit;
}
template<typename T> T fcn_mod2   (const Child2<T> &obj, const T &phit){
    return 2.2 + phit;
}

template<typename T> class Parent{
    public:
        Parent() {
            fcn_ptr = &fcn_default;
        }
        T do_something(const T &phit){
            return this->fcn_ptr(*this, phit);
        }
        T (*fcn_ptr)(const Parent &, const T &);

};

template<typename T> class Child1 : public Parent<T>{
    public:
        Child1() {
        }
        T (*fcn_ptr)(const Child1 &, const T &);

};

template<typename T> class Child2 : public Parent<T>{
    public:
        Child2() {
        }
        T (*fcn_ptr)(const Child2 &, const T &);

};

typedef double lrtType;

int main(){
    std::vector< Parent<lrtType> * > objects;

    Child1<lrtType> *test11 = new Child1<lrtType>();
    objects.push_back(test11);

    Child1<lrtType> *test12 = new Child1<lrtType>();
    test12->fcn_ptr = &fcn_mod1;
    objects.push_back(test12);

    Child2<lrtType> *test2 = new Child2<lrtType>();
    test2->fcn_ptr = &fcn_mod2;
    objects.push_back(test2);

for (size_t i = 0; i < objects.size(); ++i) {
        std::cout << objects[i]->do_something(2) << std::endl;
}

    cout << "test" << endl;
}

它产生:

5.2
5.2
5.2
test

我在期待:

5.2
3.2
4.2
test

我的理解是,矢量对象的类型为,因此调用自己的方法,而不是孩子的方法。

我几乎已经使用“奇怪的重复模板模式”破解了它,但我在向量对象的初始化过程中遇到了最后一个问题。

#include <iostream>
#include <vector>
#include <cstdlib>

using namespace std;

template<class Child, typename T> class Parent;
template<typename T> class Child1;
template<typename T> class Child2;

template<typename T> T fcn_mod1   (const Child1<T> &obj, const T &phit){
    return 1.2 + phit;
}
template<typename T> T fcn_mod2   (const Child2<T> &obj, const T &phit){
    return 2.2 + phit;
}

template<class Child, typename T> class Parent{
    public:
        Parent() {
            fcn_ptr = &Parent::fcn_default;
        }
        T do_something(const T &phit){
            return static_cast<Child*>(this)->fcn_ptr(static_cast<Child*>(this), phit);
        }
        T (*fcn_ptr)(const Child &, const T &);
    private:
        static T fcn_default(const Child &obj, const T &phit){
            return 3.2 + phit;
        }
};

template<typename T> class Child1 : public Parent<Child1<T>,T>{
    public:
        Child1() {
        }
        T (*fcn_ptr)(const Child1 &, const T &);

};

template<typename T> class Child2 : public Parent<Child2<T>,T>{
    public:
        Child2() {
        }
        T (*fcn_ptr)(const Child2 &, const T &);

};

typedef double lrtType;

int main(){
    std::vector< Parent<lrtType> * > objects;

    Child1<lrtType> *test11 = new Child1<lrtType>();
    objects.push_back(test11);

    Child1<lrtType> *test12 = new Child1<lrtType>();
    test12->fcn_ptr = &fcn_mod1;
    objects.push_back(test12);

    Child2<lrtType> *test2 = new Child2<lrtType>();
    test2->fcn_ptr = &fcn_mod2;
    objects.push_back(test2);

for (size_t i = 0; i < objects.size(); ++i) {
        std::cout << objects[i]->do_something(2) << std::endl;
}

    cout << "test" << endl;
}

** +++++ UPDATE +++++ **

如果我将一个成员添加到子类,我就无法从fcn_mod2内部访问它。也许虚拟功能可以帮助吗?

#include <iostream>
#include <vector>
#include <cstdlib>

using namespace std;

template<typename T> class Parent;
template<typename T> class Child1;
template<typename T> class Child2;

template<typename T> T fcn_default(const Parent<T> &obj, const T &phit){
    return 3.2 + phit;
}
template<typename T> T fcn_mod1   (const Parent<T> &obj, const T &phit){
    return 1.2 + phit;
}
template<typename T> T fcn_mod2   (const Parent<T> &obj, const T &phit){
    return 2.2 + phit + param2*0.001;
}

template<typename T> class Parent{
    public:
        Parent() {
            fcn_ptr = &fcn_default;
        }
        T do_something(const T &phit){
            return this->fcn_ptr(*this, phit);
        }
        T (*fcn_ptr)(const Parent &, const T &);

};

template<typename T> class Child1 : public Parent<T>{
    public:
        Child1() {
        }

};

template<typename T> class Child2 : public Parent<T>{
    public:
        Child2() {
        }
        T param2;

};

typedef double lrtType;

int main(){
    std::vector< Parent<lrtType> * > objects;

    Child1<lrtType> *test11 = new Child1<lrtType>();
    objects.push_back(test11);

    Child1<lrtType> *test12 = new Child1<lrtType>();
    test12->fcn_ptr = &fcn_mod1;
    objects.push_back(test12);

    Child2<lrtType> *test2 = new Child2<lrtType>();
    test2->fcn_ptr = &fcn_mod2;
    test2->param2 = 4;
    objects.push_back(test2);

    for (size_t i = 0; i < objects.size(); ++i) {
        std::cout << objects[i]->do_something(2) << std::endl;
    }

    cout << "test" << endl;
}

1 个答案:

答案 0 :(得分:1)

您遇到的问题是您的子类包含与Parent类中的名称相同的其他函数指针字段。这通常不是你想要的,因为这些类中会有两个指针。为什么不在父类中只使用一个指针。 因此,您应该删除子类中的函数指针。

您在第二个解决方案中遇到的下一个问题是您尝试使用运行时虚拟调度Parent s的向量)编译时间&#34;虚拟& #34;发送(奇怪的重复模板模式)。这是不可能的。如果您想要运行时虚拟调度,则必须使用虚拟函数。

如果没有使用函数指针的特殊原因,只需使用虚方法,即:

template<typename T> class Parent{
public:
    virtual T fcn(const Parent<T> &obj, const T &phit){ return 3.2 + phit; }
};

template<typename T> class Child1 : public Parent<T>{
public:
    T fcn(const Parent<T> &obj, const T &phit) override { return 2.2 + phit; }
};

template<typename T> class Child2 : public Parent<T>{
public:
    T fcn(const Parent<T> &obj, const T &phit) override { return 1.2 + phit; }
};

这应该适用于您的场景。如果这不是您想要的,请澄清您的问题。