指向类模板的指针

时间:2010-08-25 14:27:52

标签: c++

这是可编译的代码,问题仍然存在

#include <iostream>   
#include <string>    

template<typename A,typename B,typename C>   
class Mesh{   
    public:   
    Mesh(){}   
    Mesh(std::string file){   
    A foo;   
    std::cout <<  file << endl;   
    }   
};    

template<typename A, typename B,typename C>    
class Eq{    
public:    
  Mesh<A,B,C>* pmesh;      
  Eq() {}
  Eq(Mesh<A,B,C> *pmesh_){
      pmesh = pmesh_;
  }
};

template<typename A, typename B,typename C>
class Pipe{
public:
  Mesh<A, B,C> mesh;
  Eq<A, B, C> eq1;

  Pipe(){}
  Pipe(std::string file){
      mesh = Mesh<A, B, C>(file);
      eq1 = Eq<A,B,C>(&mesh);
      std::cout << "P:"<<&mesh << " ";
  }
};

template<typename A,typename B, typename C>
class Simulator {
public:
    Pipe<A,B,C> pipe;

    Simulator(){}
    Simulator(std::string file){
        pipe = Pipe<A,B,C>(file);
        std::cout << "S:"<<&(pipe.mesh)<<" ";
    }
};

using namespace std;
int main() {
    typedef double A;
    typedef double B;
    typedef int  C;

    Simulator< A, B, C> simu("mesh");
}

该计划的出口是


P:0018FE44 S:0018FE3C

我认为问题出在管道声明中,如果我将sinulator定义为

template<typename A,typename B, typename C>    
class Simulator {   
public:
    Pipe<A,B,C>*  ppipe;

Simulator(){}
    Simulator(std::string file){
        ppipe = new Pipe<A,B,C>(file);
        std::cout << "S:"<<&(ppipe->mesh)<<" ";
    }
};

输出

目 P:00308F08 S:00308F08

任何想法,为什么第一个代码错了?

2 个答案:

答案 0 :(得分:0)

您的代码的编译版本不会显示相同的行为:

#include <iostream>
template<typename A> class Mesh{public: A foo; };

template<typename A>
struct Eq{
  Mesh<A>* pmesh;
  Eq(Mesh<A> *pmesh_){
      pmesh = pmesh_;
  }
  Eq() {}
};

template<typename A>
struct Pipe{
  Mesh<A> mesh;
  Eq<A> eq1;

  Pipe() {
      mesh = Mesh<A>();
      eq1 = Eq<A>(&mesh);
      std::cout << "P:"<<&mesh << " ";
  }
};
template<typename A>
struct Sim {
    Sim() {
        Pipe<A> pipe;
        std::cout << "S:"<<&(pipe.mesh)<<" ";
    }
};

int main() {
    Sim<int> bar;
}

运行它:

[@foomanchu]$ ./temp
P:0x7fffffffeaf0 S:0x7fffffffeaf0 [@foomanchu]$ 

答案 1 :(得分:0)

问题在于您在Simulator构造函数中的副本。这段代码应该让事情变得更加明显。

这与模板无关。

#include <iostream>

struct Mesh{ Mesh() { std::cout << "M:" << this << " ";} };

struct Pipe{
  Mesh mesh;

  Pipe() { std::cout << "PX:" << &mesh << " "; }
  Pipe(int file){
      std::cout << "P1:"<<&mesh << " ";
      mesh = Mesh();
      std::cout << "P2:"<<&mesh << " ";
  }
};

struct Simulator {
    Pipe pipe;

    Simulator(){
        std::cout << "S1:"<<&(pipe.mesh)<<" ";
        pipe = Pipe(2);
        std::cout << "S2:"<<&(pipe.mesh)<<" ";
    }
};

int main() {
    Simulator simu;
}

输出:

:!./temp2
M:0x7fffffffea97 PX:0x7fffffffea97   <-- the setup of Simulator, before the constructor
S1:0x7fffffffea97
    M:0x7fffffffea96  <-- setup of the Pipe object, before the Pipe constructor
    P1:0x7fffffffea96 M:0x7fffffffea95 P2:0x7fffffffea96
S2:0x7fffffffea97

当您调用Simulator构造函数时,它首先创建对象。由于其中一个成员是“Pipe pipe”,因此该对象是在内存位置ea97创建的。然后我们显式调用Pipe(std :: string)构造函数来创建另一个对象。

在Pipe构造函数中,同样的事情正在发生。我们已经在ea96上有一个Mesh对象,但我们创建了另一个(在ea95)并使用内置的复制功能将其复制到该位置。

然后我们回到Simulator构造函数,在那里将新创建的Pipe对象复制到SimulatorObject.pipe(ea97)的位置。

编辑:删除一些无关紧要的部分......这样你就可以清楚地看到每个构造函数的调用时间。

您正在寻找的语法可能是

struct Simulator {
    Pipe pipe;

    Simulator(): pipe(2){
        std::cout << "S1:"<<&(pipe.mesh)<<" ";
    }
};

这将在“就地”模拟器内初始化Pipe对象。请注意,这不是什么大问题。您的对象将在它们应该复制时复制。

如果你有一个无法复制的对象(它管理数据库连接或其他东西),你可以通过创建一个复制构造函数和一个都是“private:”的operator = overload来禁止它。