简体   繁体   中英

pointer to class template

Here is the compilable code and the problem is still there

#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");
}

The Outlet of the program is

mesh
P:0018FE44 S:0018FE3C

I think the problem is in the declaration of pipe, if I define sinulator as

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)<<" ";
    }
};

the output is

mesh P:00308F08 S:00308F08

any idea, why the first code is wrong ??

A compiling version of your code does not show the same behavior:

#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;
}

Running it:

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

The problem is with your copy in the Simulator constructor. This code should make things a bit more obvious.

This has nothing to do with templates.

#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;
}

output:

:!./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

When you call the Simulator constructor, it first creates the object. Since one of the members is "Pipe pipe", that object is created at memory location ea97. Then we explicitly call the Pipe(std::string) constructor to create another object.

In the Pipe constructor, the same thing is happening. We already have a Mesh object at ea96, but we create another one (at ea95) and copy it into that location with the built-in copy function.

Then we're back to the Simulator constructor, where the newly created Pipe object is copied to the location of SimulatorObject.pipe (ea97).

EDIT: removing a few more pieces that don't matter... so you can see clearly when each constructor is being called.

The syntax you're looking for is probably

struct Simulator {
    Pipe pipe;

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

This will initialize the Pipe object inside Simulator "in-place". Note that this isn't a really big deal. Your objects will copy when they're supposed to.

If you have an object that can't be copied (it manages a database connection or something), you can forbid that by creating a copy constructor and an operator= overload that are both "private:"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM