Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;类方法,返回向量<;子类>;_C++_Stl_Polymorphism - Fatal编程技术网

C++ C++;类方法,返回向量<;子类>;

C++ C++;类方法,返回向量<;子类>;,c++,stl,polymorphism,C++,Stl,Polymorphism,我在为一个类编写一个方法时遇到了一些问题。我有班级符号和班级终端。类终端扩展了类符号,但是类符号的一个方法需要返回一个向量。例如: #ifndef SYMBOL_H #define SYMBOL_H #include "terminal.h" #include <vector> using namespace std; class symbol { public: vector<terminal> first(); virtua

我在为一个类编写一个方法时遇到了一些问题。我有班级符号和班级终端。类终端扩展了类符号,但是类符号的一个方法需要返回一个向量。例如:

#ifndef SYMBOL_H
#define SYMBOL_H

#include "terminal.h"
#include <vector>

using namespace std;

class symbol {
   public:
        vector<terminal> first();
        virtual void polymorphable();
};

#endif
但是,在执行此操作时,我在构建时会遇到两个错误,其中一个错误在前面:“terminal”:未声明的标识符(位于定义向量函数的行上),以及“symbol”:基类未定义(位于具有terminal类定义的行上)


如何解决“a需要b”、“b需要a”问题?

使用避免循环依赖关系

class terminal;

class symbol
{
  std::vector<terminal> first();
  // ...
};
类终端;
类符号
{
std::vector first();
// ...
};
有一种推测,这种方法是按照C++标准定义的。 @本·沃伊特指出:

C++03标准第17.6.4.8节说:

“特别是,在以下情况下,效果是未定义的:……如果在实例化模板组件时将不完整的类型用作模板参数
,除非该组件特别允许


正在讨论
std::vector f();
是否是
std::vector
的一个实例。如果那里的答案证明是,那么这个答案就没有用,我将删除它,否则它仍然有效。

使用避免循环依赖关系

class terminal;

class symbol
{
  std::vector<terminal> first();
  // ...
};
类终端;
类符号
{
std::vector first();
// ...
};
有一种推测,这种方法是按照C++标准定义的。 @本·沃伊特指出:

C++03标准第17.6.4.8节说:

“特别是,在下列情况下,影响是未定义的:。。。如果在实例化模板组件时将不完整类型用作模板参数
,除非该组件特别允许


是否
std::vector f()
std::vector
的一个实例,正在讨论。如果答案证明是正确的,那么这个答案就无效,我将删除相同的答案,否则这个答案仍然有效。

我觉得奇怪的是,重复出现的模板模式可以让你摆脱这个问题:

template<typename terminal_type>
class symbol_pattern
{
   public:
        std::vector<terminal_type> first();
        virtual void polymorphable();
};

class terminal : public symbol_pattern<terminal>
{
};

typedef symbol_pattern<terminal> symbol;
模板
类符号
{
公众:
std::vector first();
虚空可变形();
};
类终端:公共符号\u模式
{
};
typedef符号\图形符号;

我认为奇怪的重复模板模式可以让您摆脱这种模式:

template<typename terminal_type>
class symbol_pattern
{
   public:
        std::vector<terminal_type> first();
        virtual void polymorphable();
};

class terminal : public symbol_pattern<terminal>
{
};

typedef symbol_pattern<terminal> symbol;
模板
类符号
{
公众:
std::vector first();
虚空可变形();
};
类终端:公共符号\u模式
{
};
typedef符号\图形符号;
编辑:标准可能不允许以下内容(参见注释)。在这种情况下,您根本无法拥有适当的循环依赖关系:如果
a
的大小取决于
B
类型的成员的大小,但是
B
的大小取决于
a
类型的成员的大小,那么这样的定义根本没有意义

不过,我不能完全确定这是否适用于您的情况,因为您只声明了一个返回类型不完整的函数,这是允许的。见服务员;希望我们能得到一个明确的答案


只需向前声明
终端

class terminal;

class symbol
{
  std::vector<terminal> first();
  // ...
};
类终端;
类符号
{
std::vector first();
// ...
};
您可以向前声明任何只需要是不完整类型的内容。不完整类型可用于形成指针、引用、函数签名。只有在使用该类型的变量时,才需要知道完整类型。

编辑:标准可能不允许以下情况(请参见注释)。在这种情况下,您根本无法拥有适当的循环依赖关系:如果
a
的大小取决于
B
类型的成员的大小,但是
B
的大小取决于
a
类型的成员的大小,那么这样的定义根本没有意义

不过,我不能完全确定这是否适用于您的情况,因为您只声明了一个返回类型不完整的函数,这是允许的。见服务员;希望我们能得到一个明确的答案


只需向前声明
终端

class terminal;

class symbol
{
  std::vector<terminal> first();
  // ...
};
类终端;
类符号
{
std::vector first();
// ...
};

您可以向前声明任何只需要是不完整类型的内容。不完整类型可用于形成指针、引用、函数签名。只有在使用该类型的变量时,才需要知道完整的类型。

Base
类不需要知道有关
派生的
类的任何信息。这是面向对象设计的一个重要原则。您可能会将基类更改为:

class symbol {
  public:
    vector<symbol*> first();
    virtual void polymorphable();
};

Base
类不需要了解任何有关
派生类的信息。这是面向对象设计的一个重要原则。您可能会将基类更改为:

class symbol {
  public:
    vector<symbol*> first();
    virtual void polymorphable();
};

前向声明+智能指针(尽管这将在堆上而不是堆栈上存储内容…可能是不可取的)

\ifndef符号
#定义符号
#包括
#包括
使用名称空间std;
类终端;//像这样做一个提前声明
类符号{
公众:
向量优先();
虚空可变形();
};
#恩迪夫

前向声明+智能指针(尽管这现在将在堆上而不是堆栈上存储内容…可能是不可取的)

\ifndef符号
#定义符号
#包括
#包括
使用名称空间std;
类终端;//像这样做一个提前声明
类符号{
公众:
向量优先();
虚空可变形();
};
#恩迪夫

而不是只有一个成员函数返回一个容器,考虑拥有<

#include <vector>

class terminal; <--- TELLING THE COMPILER MAY USE terminal in the future.

class symbol 
{        
  std::vector<terminal> first(); <--- NOTE THE COMPILER DOES NOT NEED TO KNOW HOW TO CONSTRUCT EITHER
  // ... 
};           

class terminal: public symbol  < --- TELLS COMPILER THAT terminal INHERITS symbol i.e. CONTAINING THE METHOD first
{
   int wibble; 
};  

int main()
{
    symbol s;
    return 0;
}