【问题标题】:Unable to instantiate templated class inside another class无法在另一个类中实例化模板类
【发布时间】:2013-05-09 17:26:25
【问题描述】:

我有两个类:一个是模板化的,一个不是。我正在尝试在非模板类中创建模板类的实例,并且程序将无法编译。我正在使用 Visual Studio 2012,我在 bar.h 中的这一行收到错误“IntelliSense:预期类型说明符”:

Foo<int> foo_complex(99);  

可以在类外使用这种语法(见下面的console.cpp)。我可以在类中使用空构造函数。是什么赋予了?如何在 Bar 内正确使用 Foo 的非空构造函数?

提前感谢您的帮助。我到处寻找解决方案,却一无所获。示例代码如下。为了清楚起见,类实现是内联的。

foo.h

#pragma once

template<typename T>
class Foo
{
public:
    Foo();
    Foo(int i);
};

template<typename T>
Foo<T>::Foo()
{
    std::cout << "You created an instance of Foo without a value." << std::endl;
}

template<typename T>
Foo<T>::Foo(int i)
{
    std::cout << "You created an instance of Foo with int " << i << std::endl;
}

bar.h

#pragma once

#include "foo.h"

class Bar
{
private:
    Foo<int> foo_simple;
    Foo<int> foo_complex(99); // Error ~ IntelliSense:expected a type specifier
public:
    Bar(int i);
};

Bar::Bar(int i)
{
    std::cout << "You created an instance of Bar with int " << i << std::endl;
}

console.cpp

#include "stdafx.h"
#include <iostream>
#include <string>
#include "foo.h"
#include "bar.h"

int _tmain(int argc, _TCHAR* argv[])
{
    Foo<int> foo(1);
    Bar bar(2);
    std::string any = "any";

    std::cout << std::endl;
    std::cout << "Press any key to close this window..." << std::endl;
    std::cin >> any; 
    return 0;
}

【问题讨论】:

    标签: c++ templates exception constructor instantiation


    【解决方案1】:

    在构造函数中初始化成员变量:

    class Bar
    {
    private:
        Foo<int> foo_complex;
    public:
        Bar(int i);
    };
    
    Bar::Bar(int i) : foo_complex(99)
    {
        std::cout << "You created an instance of Bar with int " << i << std::endl;
    }
    

    【讨论】:

    • 工作就像一个魅力。谢谢。页面上的其他选项可能也不错,但它们不适用于最新的 Visual Studio 编译器。
    【解决方案2】:

    你应该使用大括号初始化:

    Foo<int> foo_complex{99};
    

    C++11 允许 brace-or-equal-initializers 用于数据成员的内联初始化,因此其他有效的替代方案是(因为 Foo&lt;int&gt; 是可移动构造的):

    Foo<int> foo_complex = Foo<int>(99);
    

    并且(因为Foo&lt;int&gt; 有一个非explicit 转换构造函数采用int):

    Foo<int> foo_complex = 99;
    

    当然,就像在 C++03 中一样,您可以在构造函数的初始化列表中初始化 foo_complex 数据成员。

    【讨论】:

    • 选项 1:抛出 10 个错误,包括 c2511 "Bar::Bar(int) : 在 'Bar' 中找不到重载的成员函数" 和 c2664 "Bar::Bar( const Bar&) : 无法将参数 2 从 'int' 转换为 'const Bar &'" 以及一堆语法错误(预期的 ';、意外的标记、语法错误 'public' 等)。 选项 2选项 3 抛出:错误 C2864:“'Bar::fox_complex' 只能在类中初始化静态 const 整数数据成员”。 **选项 3:
    • 看起来 Visual Studio 的“2012 年 11 月 CTP v120”编译器不完全符合 C++11。对于更完整的编译器,这些可能都是不错的选择。
    • @kseier:是的,似乎是这样。可能VC11只支持最后一个,C++03风格的选项(在构造函数的初始化列表中初始化)
    【解决方案3】:

    这是试图声明一个函数:

    Foo<int> foo_complex(99);
    

    我认为这是说您需要一个类型说明符作为参数。你需要在构造函数中构造这个对象,而不是在类定义中。

    【讨论】:

      【解决方案4】:

      当你声明一个对象为成员变量时,你不能初始化它,你必须在包含的类构造函数初始化列表中进行:

      Bar::Bar(int i)
          : foo_complex(99)
      {
          // ...
      }
      

      如果您的编译器足够新以支持C++11 uniform initialization,那么您应该可以做到,但语法略有不同:

      Foo<int> foo_complex{99};
      

      注意大括号而不是括号。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-06
        • 2013-09-12
        • 1970-01-01
        • 2015-08-26
        相关资源
        最近更新 更多