前向声明被忽略?

时间:2015-10-06 21:11:49

标签: c++ templates undefined

我有下面的类(它基本上是std :: vector的包装器),其中一个函数返回一个AInteger类型的变量(它基本上是int的包装器)。现在类型AInteger在整个类中被多次使用,但编译器开始在一个非常特定的位置抱怨。当我删除“getSize()”函数时,一切都编译得很好。

相互包容,所以我需要前进声明才能使一切工作。

其中一个问题是AList类是一个模板,因此无法将定义移动到.cpp文件(这通常可以解决问题)。

我做错了什么?

这是班级:

#ifndef ALIST_H
#define ALIST_H

#include <vector>

#include "AInteger.h"

class AInteger;

template<typename VALUE>
class AList {
public:
    AList() {
    }

    AList(const std::vector<VALUE> list) {
        value = list;
    }

    ~AList() {
    }

    operator const std::vector<VALUE>() const {
        return value;
    }

    std::vector<VALUE> toStdVector() const {
        return value;
    }

    VALUE operator [](const AInteger index) const {
        return value.at(index);
    }

    void add(const VALUE value) {
        this->value.push_back(value);
    }

    VALUE get(const AInteger index) const {
        return value[index];
    }

    AInteger getSize() const { // ERROR OCCURS HERE
        return value.size();
    }

    void remove(const AInteger index) {
        value.erase(index);
    }

private:
    std::vector<VALUE> value;
};

#endif

输出:

1>------ Build started: Project: ALibrary, Configuration: Debug Win32 ------
1>  ASocket.cpp
1>d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(43): error C2027: use of undefined type 'AInteger'
1>  d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(8): note: see declaration of 'AInteger'
1>  d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(53): note: see reference to class template instantiation 'AList<VALUE>' being compiled
1>  AInteger.cpp
1>d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(43): error C2027: use of undefined type 'AInteger'
1>  d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(8): note: see declaration of 'AInteger'
1>  d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(53): note: see reference to class template instantiation 'AList<VALUE>' being compiled
1>  AHttpRequest.cpp
1>d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(43): error C2027: use of undefined type 'AInteger'
1>  d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(8): note: see declaration of 'AInteger'
1>  d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(53): note: see reference to class template instantiation 'AList<VALUE>' being compiled
1>  ABoolean.cpp
1>d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(43): error C2027: use of undefined type 'AInteger'
1>  d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(8): note: see declaration of 'AInteger'
1>  d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(53): note: see reference to class template instantiation 'AList<VALUE>' being compiled
1>  Generating Code...
1>  Compiling...
1>  AString.cpp
1>  Generating Code...
2>------ Build started: Project: BitHoarder, Configuration: Debug Win32 ------
2>  SystemHandler.cpp
2>d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(43): error C2027: use of undefined type 'AInteger'
2>  d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(8): note: see declaration of 'AInteger'
2>  d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(53): note: see reference to class template instantiation 'AList<VALUE>' being compiled
2>  Main.cpp
2>d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(43): error C2027: use of undefined type 'AInteger'
2>  d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(8): note: see declaration of 'AInteger'
2>  d:\programs\programming\visual studio projects\c++\alibrary\alibrary\alist.h(53): note: see reference to class template instantiation 'AList<VALUE>' being compiled
2>  Generating Code...
========== Build: 0 succeeded, 2 failed, 0 up-to-date, 0 skipped ==========

如果需要更多代码,请询问,我会提供。

谢谢!

编辑: 这是“AInteger.h”中的代码

#ifndef AINTEGER_H
#define AINTEGER_H

#include "AList.h"

template<typename VALUE>
class AList;

class AInteger {
public:
    AInteger();
    AInteger(const int);
    ~AInteger();

    operator const int() const;

    int toInt() const;

    AInteger operator=(const AInteger &);
    AInteger & operator++();
    AInteger & operator--();

    AList<AInteger>splitByNumber(const AInteger &);

private:
    int value;
};

#endif

为了让事情更加令人困惑,下面的类做了完全相同的事情并没有产生错误:

#ifndef ADICTIONARY_H
#define ADICTIONARY_H

#include <map>

#include "AInteger.h"

class AInteger;

template<typename KEY, typename VALUE, typename COMPARE = std::less<KEY>>
class ADictionary {
public:
    ADictionary() {
    }

    ADictionary(const std::map<KEY, VALUE, COMPARE> dictionary) {
        value = dictionary;
    }

    ~ADictionary() {
    }

    operator const std::map<KEY, VALUE, COMPARE>() const {
        return value;
    }

    std::map<KEY, VALUE, COMPARE> toStdMap() const {
        return value;
    }

    VALUE operator [](const KEY key) const {
        return value.at(key);
    }

    void add(const KEY key, const VALUE value) {
        this->value.insert(std::make_pair(key, value));
    }

    VALUE get(const KEY key) const {
        return value[key];
    }

    AInteger getSize() const { // No error here
        return value.size();
    }

    void remove(const KEY key) {
        value.erase(value.find(key));
    }

private:
    std::map<KEY, VALUE, COMPARE> value;
};

#endif

2 个答案:

答案 0 :(得分:4)

getSize()的实施必须创建AInteger的实例。只有在知道AInteger的完整定义时才可以这样做。您无法创建仅向前声明的类型的实例。

这正是编译器告诉你的:error C2027: use of undefined type 'AInteger'。它不会忽略前向声明,但会告诉您它不够。

对于#include "AInteger.h",您不会显示其内容,但可能存在以下问题:

  • Buggy包含头文件中的guard会导致编译器跳过定义。
  • 头文件定义了一个名称相似的不同类型。
  • AInteger的定义位于命名空间内。

答案 1 :(得分:2)

出现问题的答案在Christian Hackl的答案中得到了很好的回答,通常我会把它放在那里,但我无法解释OP如何在评论中正确解决这个问题。

首先修订了AInteger.h

#ifndef AINTEGER_H
#define AINTEGER_H

template<typename VALUE>
class AList;

class AInteger {
public:
    AInteger();
    AInteger(const int);
    ~AInteger();

    //operator const int() const;

    int toInt() const;

    AInteger operator=(const AInteger &);
    AInteger & operator++();
    AInteger & operator--();

    std::unique_ptr<AList<AInteger>> splitByNumber(const AInteger &);
    void splitByNumber(const AInteger &,
                       AList<AInteger> &);

private:
    int value;
};

#endif

AList.h的包含已经消失。 AList的前瞻性声明仍然是我提供了两种不同的splitByNumber方法。选一个。第一个创建并返回a pointer protected by a smart pointer。第二种方法,也是我个人的偏好,引用了调用者创建的AList。

事情对AList的内部运作一无所知,因为他们关心的是A)它存在,b)它们可以得到一个地址。

在我探索两者时请耐心等待,因为我认为它们都具有教育意义。

除了删除AInteger的前瞻声明外,

Alist.h保持不变。

两个splitByNumber候选人位于AInteger的实现文件中,该文件可以安全地包含AInteger.h和AList.h,因此可以同时完全了解两者并且可以完成所有神奇的事物AIntegersALists可以做到。

std::unique_ptr<AList<AInteger>> AInteger::splitByNumber(const AInteger & integer)
{
    std::unique_ptr<AList<AInteger>> listp(new AList<AInteger>());

    // do stuff with listp
    return listp;
}

void AInteger::splitByNumber(const AInteger & integer,
                             AList<AInteger> & list)
{
    // do stuff with list
}

使用指针版本:

std::unique_ptr<AList<AInteger>> alistp = aitest1.splitByNumber(aitest2);
alistp->add(somenumber);

使用参考版本:

AList<AInteger> alist; // first create an empty AList
aitest1.splitByNumber(aitest2, alist); // pass it into the function
alist.add(somenumber); // use the AList