c ++如何使用模板调用内部类的构造函数?

问题描述 投票:1回答:2

我想通过调用Nach(3,a)创建一个Nach对象,其中a是Mat对象。有些事情在这一点上失败了。 (Line:Graph :: Nach h = Graph :: Nach(3,a);)

Nach定义为Graph的内部类。 Graph使用两个模板。 Nach代表邻居,Mat代表材料,Masch代表机器。

#include <iostream>
#include <vector>
#include <string>

class Mat {

    public:
        int _id;
        int _type;
        double _amount;

        Mat (int id, int type, double amount );
};
Mat::Mat(int id, int type, double amount){
    std::cout<<"Mat constuktor used"<<std::endl;
    _id = id; _type = type; _amount = amount;
};




class Masch {
    public:
        int _id;
        int _rez;
        double _count;

        Masch (int id, int rez, double count );

};
Masch::Masch(int id, int rez, double count){
    std::cout<<"Masch constuktor used"<<std::endl;
    _id = id; _rez = rez; _count = count;
};


template <class V, class E>
class Graph {
    public:
        class Nach {
            public:
                int _id;
                Mat _e;

                Nach(int id, Mat e);
        };

        int num;
        std::vector<V> nodes;
        std::vector<std::vector<Nach>> _nach;

        void addVertex(V t);
        void addEdge(V a, V b, E e);

        Graph();


};
template <class V, class E> Graph<V,E>::Graph(){
    std::cout<<"Graph constuktor used"<<std::endl;
    num = 0;    
}
template <class V, class E> Graph<V,E>::Nach::Nach(int id, Mat e){
    std::cout<<"Nach constuktor used"<<std::endl;
    _id = id; _e = e;
}
template <class V, class E> void Graph<V,E>::addVertex(V t){
    nodes.push_back(t);
    _nach.push_back(std::vector<Nach>());
    num++;
}
template <class V, class E> void Graph<V,E>::addEdge(V a, V b, E e){
    int i = a._id;
    int j = b._id;
    //Graph<V, E>::Nach x(3, e);
    //_nach[j].push_back(Nach(i,e));

}

int main (){

    Mat a= Mat(0,1,0.1); 
    //Mat b= Mat(1,1,0.3);

    Masch c = Masch(0,0,0.1);

    Graph <Masch, Mat> g = Graph<Masch, Mat>();

    //std::cout << a+b <<std::endl;
    //std::cout << c <<std::endl;

    Graph<Masch, Mat>::Nach h = Graph<Masch, Mat>::Nach(3,a);

    g.addVertex(c);
    g.addVertex(c);

    //g.addEdge(c,c,a);


    return 0;

}

我希望创建一个海军类的实例。

但它引发了Mat的构造函数的调用错误。我不知道“Nach”的召唤叫“Mat”在哪里

错误消息

Hello.cpp: In instantiation of ‘Graph<V, E>::Nach::Nach(int, Mat) [with V = Masch; E = Mat]’:
Hello.cpp:94:57:   required from here
Hello.cpp:65:65: error: no matching function for call to ‘Mat::Mat()’
 template <class V, class E> Graph<V,E>::Nach::Nach(int id, Mat e){
                                                                 ^
Hello.cpp:16:1: note: candidate: Mat::Mat(int, int, double)
 Mat::Mat(int id, int type, double amount){
 ^
Hello.cpp:16:1: note:   candidate expects 3 arguments, 0 provided
Hello.cpp:7:7: note: candidate: constexpr Mat::Mat(const Mat&)
 class Mat {
       ^
Hello.cpp:7:7: note:   candidate expects 1 argument, 0 provided
Hello.cpp:7:7: note: candidate: constexpr Mat::Mat(Mat&&)
Hello.cpp:7:7: note: candidate expects 1 argument, 0 provided
c++
2个回答
2
投票

当您调用Nach构造函数时,默认构造每个成员,然后执行构造函数体。 Mat没有默认构造函数。您无法在错误消息中看到对Mat()的调用,因为调用是由编译器生成的。解决方案是使用initialisation list而不是构造然后分配。大多数情况下,构造函数体应该是空的。

template <class V, class E>
Graph<V, E>::Nach::Nach(int id, Mat e)
  : _id{id}, _e{e} {}

这直接构造成员而不是首先构造它们然后分配给它们(就像你在Java中那样)。您应该始终使用初始化列表。

还有一些我应该提及的事情。

  • 在模板参数列表中使用class有点老式。允许class向后兼容,因此应该避免。 class最初用于避免在该语言中添加另一个关键字,后来添加了typename
  • 使用一个或多个_underscores_开始标识符通常不是一个好主意。这是因为以下划线开头的标识符是为实现保留的,因此您可能会发生冲突。
  • 使用初始化列表时,构造函数参数可能与成员具有相同的名称,因此允许使用以下内容并且将按预期运行。很少有理由在成员名称中加入下划线(或任何其他字符序列)以避免冲突。

这就是我实现构造函数的方法。

template <typename V, typename E>
Graph<V, E>::Nach::Nach(const int id, const Mat e)
  : id{id}, e{e} {}

0
投票

在创建Nach嵌套类时,需要在构造函数中初始化_e成员时创建Mat(使用默认构造函数)。

您应该尝试重写构造函数以复制传递的mat:

template <class V, class E> Graph<V,E>::Nach::Nach(int id, Mat e): _e(e) {
    // _e is now initialize from a e copy before entering here.
    std::cout<<"Nach constuktor used"<<std::endl;
    _id = id;  // this could be moved as welll
}
© www.soinside.com 2019 - 2024. All rights reserved.