-1

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?
James Z
  • 12,209
  • 10
  • 24
  • 44
  • 1
    I am surprised you were able to build the executable with those commands. See [Why can templates only be implemented in the header file?](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – R Sahu Jun 20 '18 at 16:14
  • Your confusion probably comes from the first output line which is being generated by: `const Uint_32& Uint_32::UNIQUEID=Uint_32(3);`, That line is actually a lot fancier than you think. –  Jun 20 '18 at 16:17
  • @R Sahu I know that template class should have it's function definition at the time of compiling therefore I made a file that include .hpp and .cpp file in one and I just included here is it `include//lang//Class.hpp` and `include//lang//Object.hpp`. And @Frank I know this line has something to do with output my problem is not that I just can't understand why Object class non parameterized constructor is called and not parameterised? – Ravinder Singh Jun 20 '18 at 16:30
  • 2
    Breaking the rule of 3 and rule of 5 here is most likely your issue... You are expecting autogenerated code (like operator=) to behave in a certain way, which it doesn't. Implement proper move/copy operators/ctors and you will be able to trace this much easier. [See here for more on the rule of 5](https://cpppatterns.com/patterns/rule-of-five.html) – mascoj Jun 20 '18 at 16:48
  • @mascoj I make class as you said for rule of 5 but still output remains the same even assignment or move assignment are not even called since I have made a reference. I cant still figure out the calling of Object default constructor from class constructor. – Ravinder Singh Jun 21 '18 at 04:24
  • I also double check the output and even tried changing the code a bit – Ravinder Singh Jun 21 '18 at 04:25
  • I figure out my second problem its just one constructor call is for a variable in Class.cpp => ref(variable name). – Ravinder Singh Jun 21 '18 at 04:27

1 Answers1

0

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.

Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85
  • thanks for replying. I get the reason why my output is like this but can you please also tell how can I get my desired output. I mean I don't wont multiple copies of Object class in derived classes but I also want to run it in way I inherit it. – Ravinder Singh Jun 23 '18 at 05:06
  • In java we can make object of Object class and Class class and even change it accordingly to any object we want. Like if we have some Object o1 of class A, o2 of class B and obj of Object class then we can do like this obj = o1 and after few line obj = o2. Can I do the same? also In java we make Object class object like this : Object obj; I want to do the same way. – Ravinder Singh Jun 23 '18 at 05:10
  • Instances : 1) a – Ravinder Singh Jun 23 '18 at 05:12
  • 2) b , 3) Uint32::UNIQUEID and 4) Class& Object::ref=Class(); – Ravinder Singh Jun 23 '18 at 05:13
  • *"I don't wont multiple copies of Object class in derived classes"* If you think you may end up with a diamond hierarchy, then which branch of it should initialize `Object` base? Java doesn't have multiple inheritance - thus no possibility of diamond hierarchy and no concept of virtual inheritance. – Igor Tandetnik Jun 23 '18 at 05:15
  • The closest C++ has to Java's `Object` is `void*`. It's much less useful since, unlike Java, C++ doesn't have reflection. But even in Java, dropping type safety and working in terms of `Object` is a sign of a bad design, most of the time. Anyway, it's unclear what you are trying to achieve; your code doesn't make any sense to me, quite frankly. – Igor Tandetnik Jun 23 '18 at 05:17
  • (4) instantiates a `Class`, not a `Uint_32`. I'm not sure I understand what it is you are counting, exactly. – Igor Tandetnik Jun 23 '18 at 05:17
  • The code I write is very basic of my project. I tried to build a library such that I have knowledge of every class and object but since c++ is multiple inheritance I thought the every class that want to use my library must inherit the Class class but if multiple inheritance is done then at every level there will be an instance of Class class and Object class and will give me redundant data. Thus I made virtual classes. – Ravinder Singh Jun 23 '18 at 05:38
  • I am counting Object constructor calls. – Ravinder Singh Jun 23 '18 at 05:49
  • One from `a`, one from `b`, one indeed from `Class& Object::ref=Class();`, and one from `const Uint_32& Uint_32::UNIQUEID=Uint_32(3)`. The third one prints `checking`, the others print `ohk` – Igor Tandetnik Jun 23 '18 at 13:55