对以下用户定义类片段中的模板实例化问题表示怀疑

Doubt with the template instantiation problem in the below snippet of a user defined class

本文关键字:实例化 问题 怀疑 表示 用户 定义 片段      更新时间:2023-10-16

在论坛中找不到任何相关的东西,所以,请帮我写这段代码。我正在复习我的c++概念,遇到了一个奇怪的错误

#include<iostream>
using namespace std ;
class base
{
    int i ;
public:
    virtual void f(){cout<<"base" ; return ;};
};
class derived: public base
{
int j ;
public:
    void f() {cout<<"derived" ; return ;}
};
template<class T>
class test
{
public:
    test(T b) 
    {
        b.f(); cout<<endl<<" "<<sizeof(b)<<endl;
    }
};
int main()
{
base b ;
derived d;
test<derived> t(b); // cannot instantiate user defined type without typename
}

以下代码编译失败,出现以下错误:

test.cpp: In function ‘int main()’:
test.cpp:28: error: no matching function for call to ‘test<derived>::test(base&)’
test.cpp:19: note: candidates are: test<T>::test(T) [with T = derived]
test.cpp:17: note:  test<derived>::test(const test<derived>&)

我可以胡乱猜测,然后找到为什么会发生这种情况的答案。如果我从模板实例化一个新的基类,一切都很好,但这一个不行。有人能告诉我一个很好的模板实例化来源吗?规则/语义是什么,幕后发生了什么?感谢

您的测试片段有效地定义了这一点:

测试::测试(派生&(

正如错误所说,你试图调用这个:

test::test(base&(

如果我从模板实例化一个新的基类,一切都会很好。

同样,我相信,如果你通过"d"而不是"b",一切都会很好。

您应该能够在没有模板的情况下重现相同的场景:只定义了一个以"派生"为参数的成员函数,然后看看会发生什么:(

base不是一个完整的derived类型,因此您必须在模板中提供一个构造函数来填充缺失的详细信息。

template<class T> //original template
class test
{
  public:
    test(T b)
    {
      b.f();
      cout<<endl<<" "<<sizeof(b)<<endl;
    }
};

当您基于derived创建此模板的实例时,编译器会将其转换为一个类,该类本质上可以归结为这个

class derivedtest
{
  public:
    derivedtest(derived b)
    {
      b.f();
      cout<<endl<<" "<<sizeof(b)<<endl;
    }
};

不再生成默认构造函数。但是,仍然会创建一个默认的复制构造函数。

derivedtest::derivedtest(derived const&);

正如您所看到的,没有办法将base(通过引用或复制(传递到类中。

解决方案是在模板中提供一个构造函数来填充缺失的细节:

template<class T>
class test
{
  public:
    test(base const& item)
     : base(item)
    {
    }

    test(T b)
    {
      b.f();
      cout<<endl<<" "<<sizeof(b)<<endl;
    }
};

顺便说一下,你的base应该很可能有一个虚拟析构函数

并且CCD_ 5应该是CCD_ 6