【问题标题】:template class multiple inheritance constructor with this pointer doesn't work?带有此指针的模板类多重继承构造函数不起作用?
【发布时间】:2018-06-20 16:09:24
【问题描述】:

我有一个非常基本的代码牢记java。我做了一个对象和类类,但在模板中。

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

编译命令:

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

现在终于没有编译错误了。我还有一个包含 operator.hpp 的文件,其中只包含每个运算符的模板定义。

输出 当我运行可执行文件时,我得到以下输出,我可能无法理解为什么?我尝试了所有可能的方法来知道。我还运行不同版本的不同系统。

ohk hello  there  checking  hello
ohk hello  here ohk hello  here

这里发生了什么?为什么我的继承不能正确调用?我知道我不应该传递这个指针,因为它不安全,但我认为我没有其他选择。

我的问题

  1. Object&lt;T&gt;::Object(Class&lt;T&gt;&amp; myReference) 只被调用一次,但应该被调用三次。
  2. 在我看来有四个对象创建,它必须是 3 或 5(t1.cpp 中的 a 和 b 以及每个类中的 UNIEQUEID 初始化。
  3. 为什么这在构造函数调用中的 Class.cpp 文件中不起作用?
  4. 有什么方法可以检查是否可以让 Object 类调用 Object&lt;T&gt;::Object() 构造函数,以便 T = Object 类?

【问题讨论】:

  • 我很惊讶您能够使用这些命令构建可执行文件。见Why can templates only be implemented in the header file?
  • 您的困惑可能来自于由const Uint_32&amp; Uint_32::UNIQUEID=Uint_32(3); 生成的第一行输出,该行实际上比您想象的要花哨得多。
  • @R Sahu 我知道模板类在编译时应该有它的函数定义,因此我制作了一个包含 .hpp 和 .cpp 文件的文件,我只是在这里包含它@987654335 @ 和 include//lang//Object.hpp。 @Frank 我知道这一行与输出有关我的问题不是我只是不明白为什么 Object 类非参数化构造函数被调用而不是参数化?
  • 在这里打破规则 3 和规则 5 很可能是您的问题...您期望自动生成的代码(如 operator=)以某种方式运行,但事实并非如此。实施正确的移动/复制操作符/ctors,您将能够更轻松地跟踪它。 See here for more on the rule of 5
  • @mascoj 我按照你所说的 5 规则上课,但输出仍然保持不变,即使分配或移动分配甚至没有被调用,因为我已经做了参考。我仍然无法从类构造函数中找出 Object 默认构造函数的调用。

标签: c++ templates inheritance c++14 this-pointer


【解决方案1】:

您正在使用虚拟继承。最派生类负责初始化其所有虚拟基类。

当你写作时

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

您似乎期望Uint_32 构造函数调用Class&lt;Uint_32&gt;() 构造函数,然后又调用Object(*this)。但事实并非如此。由于Object 是一个虚拟基类,所以Uint_32 负责初始化它,而不是Class。由于Uint_32 没有在其初始化列表中提及它,所以使用Object 的默认构造函数(而不是单参数构造函数)。


Object(Class&lt;T&gt;&amp;) 的一个电话来自template&lt;class T&gt;const Class&lt;T&gt;&amp; Object&lt;T&gt;::ref=Class&lt;T&gt;();。这是您将Class 实例化为最派生对象的唯一地方(与另一个对象的基类子对象相反),这使得它负责调用Object 构造函数,它与Object(*this) 一起使用。


你如何计算四个实例?在您显示的输出中,单词there 出现一次,单词here 出现两次,总共构造了三个Uint_32 实例。它们是abUint_32::UNIQUEID


我不确定我是否理解你的问题 4。你是在问你是否会写作,比如说,

Object<Object<int>> obj;

?我不明白为什么不这样做,但是您可以轻松地尝试一下,然后自己看看。

【讨论】:

  • 感谢您的回复。我明白为什么我的输出是这样的原因,但你能否告诉我如何获得我想要的输出。我的意思是我不会在派生类中复制多个 Object 类,但我也想以我继承它的方式运行它。
  • 在java中,我们可以制作Object类和Class类的对象,甚至可以将它相应地更改为我们想要的任何对象。就像如果我们有一些 A 类的对象 o1、B 类的 o2 和对象类的 obj,那么我们可以像这样 obj = o1 和几行之后 obj = o2。我可以这样做吗?同样在java中,我们像这样制作Object类对象:Object obj;我也想这样做。
  • 实例:1) a
  • 2) b , 3) Uint32::UNIQUEID 和 4) Class& Object::ref=Class();
  • “我不会在派生类中复制多个 Object 类” 如果您认为最终可能会得到菱形层次结构,那么应该初始化它的哪个分支 @ 987654342@基地? Java 没有多重继承——因此没有菱形层次结构的可能性,也没有虚拟继承的概念。
猜你喜欢
  • 2017-10-20
  • 2019-12-14
  • 1970-01-01
  • 2016-03-04
  • 1970-01-01
  • 2018-09-29
  • 2013-03-25
  • 1970-01-01
相关资源
最近更新 更多