我有点困惑.前向声明和前向引用有什么区别?在我的脑海中,当你声明一个尚未实现的函数时,前向声明是不正确的?您是否必须查看指定的情况,以声明案例"前向引用"或"前向声明"?
我有一个头文件,有一些前向声明但是当我在实现文件中包含头文件时,它包含在先前的前向声明的包含之后,这会导致像这样的错误.
error: using typedef-name ‘std::ifstream’ after ‘class’
/usr/include/c++/4.2.1/iosfwd:145: error: ‘std::ifstream’ has a previous declaration.
class ifstream;
class A
{
ifstream *inStream;
}
// End of A.h
#include <ifstream>
using std::ifstream;
#include "A.h"
// etc
Run Code Online (Sandbox Code Playgroud)
什么是解决这个问题的常态?
提前致谢.
我想知道为什么C++的declare-before-use规则不能保存在类中.
看看这个例子:
#ifdef BASE
struct Base {
#endif
struct B;
struct A {
B *b;
A(){ b->foo(); }
};
struct B {
void foo() {}
};
#ifdef BASE
};
#endif
int main( ) { return 0; }
Run Code Online (Sandbox Code Playgroud)
如果定义了BASE,则代码有效.
在A的构造函数中,我可以使用尚未声明的B :: foo.
为什么这有效,而且大多数情况下,为什么只能在课堂上工作?
我已经看到很多关于何时使用前向声明而不是包含头文件的解释,但是很少有人解释为什么这样做很重要.我见过的一些原因包括:
来自.net背景我发现标题管理令人沮丧.我有这种感觉我需要掌握前向声明,但到目前为止我一直在报废.
为什么编译器不能为我工作并使用一种机制(包括)找出我的依赖关系?
前向声明如何加速编译,因为在某些时候引用的对象需要编译?
我可以购买降低复杂性的论据,但这样做的实际例子是什么呢?
我的印象是C++中的所有内容必须在使用之前声明.
事实上,我记得读过这就是为什么auto在返回类型中使用C++ 0x无效的原因decltype:编译器在评估函数体之前必须知道声明的类型.
想象一下,当我注意到(经过很长一段时间)以下代码实际上完全合法时,我感到很惊讶:
[编辑:更改示例.]
class Foo
{
Foo(int x = y);
static const int y = 5;
};
Run Code Online (Sandbox Code Playgroud)
所以现在我不明白:
考虑以下代码:
namespace foo {}
class A
{
class B
{
};
friend int foo::bar( B& );
};
namespace foo
{
int bar( A::B& )
{
}
}
Run Code Online (Sandbox Code Playgroud)
G ++ 4.4.3告诉我:
friendfun-innerclass.cpp:21:错误:'int foo :: bar(A :: B&)'应该在'foo'中声明
但我无法宣布:
namespace foo
{
int bar( A::B& );
}
Run Code Online (Sandbox Code Playgroud)
在A类定义之前因为A :: B尚未声明.而且我不能明确声明"A类:: B",声明类BI必须给出类A的定义,据我所知,"朋友"声明必须在A类的定义中.
对我来说很奇怪的是,如果我从命名空间foo中取出函数"bar()",一切正常.对我来说似乎违反直觉的是,在命名空间内部或不在命名空间内部使用函数会改变编译器是否接受类中的友元函数声明.
有没有人知道如何通过这种方式来构建所有声明并使其发挥作用?
我已经制作了两个相同的类X和Y,并且指向了彼此.请参阅下面的代码Xh,Yh与所有X和Y的互换相同.但是,此代码在我的方法Connect中出错(错误C2027:使用未定义类型'Y').在Xh中,我已经向前声明了类Y,但它不知道Y有一个名为SetXPointer的方法.因此我还需要转发声明这个方法,对吗?
如果我尝试这样做(添加行Y :: SetXPointer(X*pX_in);在行类Y;)下,我得到编译器错误C2761:'void Y :: SetXPointer(X*)':成员函数重新声明不允许.有没有办法在类X中使用类Y的公共方法?
// X.h
#pragma once
#include "Y.h"
// Forward declaration
class Y;
class X
{
public:
X(void) : data(24) {};
~X(void) {};
int GetData() { return data; }
void SetYPointer(Y* pY_in) { pY = pY_in; }
Y* GetYPointer() { return pY; }
void Connect(Y* Y_in) { pY = Y_in; Y_in->SetXPointer(this); }
private:
int data;
Y *pY;
};
Run Code Online (Sandbox Code Playgroud) 我正在将现有的.NET类库改编为可移植类库.我使用配置文件78(.NET 4.5,Windows Store 8,Windows Phone 8)支持配置文件158(也针对Silverlight 5),因为我希望能够编译unsafe原始库的代码.
.NET库包含很多标记的类[Serializable],所以我实现了一个包含虚拟SerializableAttribute实现的支持PCL库:
public class SerializableAttribute : Attribute { }
Run Code Online (Sandbox Code Playgroud)
它是从主PCL库中引用的.
为了充分利用.NET应用程序中的主PCL库,同时避免类型名称冲突,我还准备了一个.NET支持库(具有与PCL支持库相同的强名称),包含类型转发声明:
[assembly: TypeForwardedTo(SerializableAttribute)]
Run Code Online (Sandbox Code Playgroud)
并在我的.NET应用程序中显式引用.NET支持库而不是PCL库.
在准备好所有这些并能够成功编译PCL适配库之后,我将重新使用原始.NET库中的单元测试,现在引用PCL主库和.NET支持库.
这通常非常有效,但对于包含[Serializable]带有[OnDeserialized]装饰方法的类的单元测试:
[Serializable]
public class Foo
{
[OnDeserialized]
private void DoSomething(StreamingContext context) { }
}
Run Code Online (Sandbox Code Playgroud)
我得到以下内容TypeLoadException:
在程序集"MyPclAssembly"中键入"Foo"的方法为"DoSomething",其序列化属性的签名不正确.
(可以注意到,OnDeserializedAttribute 它包含在便携式子集中,可能是因为它在[DataContract]序列化中也被识别出来.)
在原始.NET库上运行单元测试时,我没有获得异常.我仔细分析了Foo类中的方法签名,它完全符合这些(de-)序列化辅助方法应具有的签名,请参见此处.我也试图改变的可见性[OnDeserialized]方法internal和public,但无济于事.
使用PCL库时出现此异常的原因是什么,我该怎么做才能避免它?
编辑我已经检查了PCL库的IL …
c# serialization attributes forward-declaration portable-class-library
我有两节课,foo和bar.
foo.h #includes bar.h并包含一个std::vector指向bar对象的指针.在运行时期间的某个时刻,bar必须访问指向其他bar对象的指针向量.因此,foo包含一个getBarObjects()返回指针数组的方法.
因此,我foo在bar.h中转发声明.我显然还要转发声明我正在使用的方法 - foo::getBarObjects().当这返回指针数组时bar,我陷入了恶性循环.
我无法转发声明Bar然后只是转发声明getBarObjects(),因为这导致"不允许不完整的类型名称".
foo.h中:
#include "bar.h"
#include <vector>
class foo {
public:
foo();
~foo();
std::vector<bar*> getBarObjects();
private:
std::vector<bar*> barObjects;
}
Run Code Online (Sandbox Code Playgroud)
bar.h:
class foo;
std::vector<bar*> foo::getBarObjects(); // error, doesn't know bar at this point
class bar {
public:
bar(foo *currentFoo);
~bar();
bool dosth();
private:
foo *thisFoo;
}
Run Code Online (Sandbox Code Playgroud)
bar.cpp:
#include "bar.h"
bool bar(foo …Run Code Online (Sandbox Code Playgroud) 以下代码编译并给出结果(GCC和clang):
template <typename T> struct Derived;
struct Base
{
template <typename T>
void foo(T * const t)
{
dynamic_cast<Derived<T> * const>(this)->bar(t);
}
};
template <typename T>
struct Derived : Base
{
void bar(T const *) const { }
};
Run Code Online (Sandbox Code Playgroud)
代码调用fooin Base到barin Derived.
作为参考,以下代码无法编译:
struct Derived2;
struct Base2
{
template <typename T>
void foo(T * const t)
{
dynamic_cast<Derived2 * const>(this)->bar(t);
}
};
struct Derived2 : Base2
{
template <typename T>
void bar(T const *) …Run Code Online (Sandbox Code Playgroud)