Search code examples
c++templatesinheritancec++14this-pointer

template class multiple inheritance constructor with this pointer doesn't work?


I have a very basic code keeping in mind of java. I made a Object and Class class but in Template.

Object.hpp

#ifndef _OBJECT_HPP_
#define _OBJECT_HPP_

namespace library{

template<class T> class Object;
template<class T> class Class;
class Uint_32;

template<class T>
class Object{
public:
  const static Uint_32& UNIQUEID;
private:
  const Class<T>& myClass;
  const static Class<T>& ref;
protected:
  Object(Class<T>& myReference);
  Object();
};

}

#endif

Object.cpp

#include "include//lang//template//Object.hpp"
#include "include//lang//template//Class.hpp"
#include "include//lang//Uint_32.hpp"
#include "iostream"
using namespace std;
using namespace library;

template<class T>const Uint_32& Object<T>::UNIQUEID=Uint_32(1);

template<class T>const Class<T>& Object<T>::ref=Class<T>();


template<class T>
Object<T>::Object(Class<T>& myReference):myClass(myReference){cout<<" 
checking ";}



template<class T>
Object<T>::Object():myClass(ref){cout<<"ohk";}

Class.hpp

#ifndef _CLASS_HPP_
#define _CLASS_HPP_

#include"include//lang//Object.hpp"

namespace library{
template<class T>
class Class:public virtual Object<T>{
public:
  Class();
  const static Uint_32& UNIQUEID;
};
}

#endif

Class.cpp

#include "include//lang//template//Class.hpp"
#include "include//lang//Uint_32.hpp"
using namespace library;

template<class T>const Uint_32& Class<T>::UNIQUEID=Uint_32(2);

template<class T>
Class<T>::Class():Object(*this){
cout<<" hello ";
}

Uint_32.hpp

#ifndef  _UINT_32_HPP_
#define _UINT_32_HPP_

#include "include//lang//Class.hpp"
#include "include//lang//Operators.hpp"


namespace library{

class Uint_32:public virtual Class<Uint_32>{
public:
  Uint_32();
  Uint_32(const int&&);
  friend Uint_32& operator+(const Uint_32& a,const Uint_32& b);
  friend Uint_32& operator<<(const Uint_32& a,const int& b);
  const static Uint_32& UNIQUEID;
private:
  int value;
};
}

#endif

Uint_32.cpp

#include "include//lang//Uint_32.hpp"
using namespace library;

const Uint_32& Uint_32::UNIQUEID=Uint_32(3);

Uint_32::Uint_32():Class<Uint_32>(){
value=0;
cout<<" here ";
}

Uint_32::Uint_32(const int&& val):Class<Uint_32>(){
value=val;
cout<<" there ";
}

t1.cpp

#include "include//lang//Uint_32.hpp"
using namespace library;

int main()
{
 cout<<"\n";
 Uint_32 a,b;
 return 0;
}

Compile Command :

g++ -std=c++14 -I. -c src//lang//Uint_32.cpp -o obj//lang//Uint_32.o
g++ -std=c++14 -I. src//test//t1.cpp obj//lang//Uint_32.o -o bin//test

there is no compilation error for now at last. I have one more file with operators.hpp that just contain a template definition for every operator.

OUTPUT when I run the executable I get the following output and I probably cannot understand why? I tried every possible way to know. I also run over different system with different version.

ohk hello  there  checking  hello
ohk hello  here ohk hello  here

What is happening here? Why my inheritance doesn't call correctly? I know I should not pass this pointer as it's not safe but I think I don't have alternative.

My problems

  1. Object<T>::Object(Class<T>& myReference) is being called only once but that should be called thrice.
  2. there are four object creation in my point it must be either 3 or 5 (a and b in t1.cpp and UNIEQUEID initialisation in every class.
  3. why this is not working in Class.cpp file in constructor call?
  4. Is there any way I can check if I can make Object class to call Object<T>::Object() constructor so that T = Object class?

Solution

  • You are using virtual inheritance. The most-derived class is responsible for initializing all its virtual base classes.

    When you write

    Uint_32::Uint_32(const int&& val):Class<Uint_32>(){ ... }
    

    you appear to expect Uint_32 constructor to call Class<Uint_32>() constructor, and that in turn to call Object(*this). But that's not what happens. Since Object is a virtual base class, Uint_32 is responsible for initializing it, not Class. And since Uint_32 doesn't mention it in its initializer list, Object's default constructor is used (rather than the single-parameter one).


    That one call to Object(Class<T>&) comes from template<class T>const Class<T>& Object<T>::ref=Class<T>();. This is the only place where you instantiate Class as the most-derived object (as opposed to a base class subobject of another object), which makes it responsible for calling Object constructor, which it does with Object(*this).


    How do you count four instances? In the output you show, the word there occurs once and the word here twice, for a total of three instances of Uint_32 being constructed. Those are a, b and Uint_32::UNIQUEID.


    I'm not sure I understand your question 4. Are you asking whether you can write, say,

    Object<Object<int>> obj;
    

    ? I don't see why not, but you can easily try it and see for yourself.