我在头文件中有一些代码如下:
#include <memory>
class Thing;
class MyClass
{
std::unique_ptr< Thing > my_thing;
};
Run Code Online (Sandbox Code Playgroud)
如果我有一个CPP这个头不包含的Thing类型定义,那么这并不在VS2010 SP1的编译:
1> C:\ Program Files(x86)\ Microsoft Visual Studio 10.0\VC\include\memory(2067):错误C2027:使用未定义类型'Thing'
替换std::unique_ptr为std::shared_ptr和编译.
所以,我猜这是当前VS2010 std::unique_ptr的实现,需要完整的定义,而且完全依赖于实现.
或者是吗?它的标准要求中是否有某些东西使得std::unique_ptr实施只能使用前向声明?感觉很奇怪,因为它应该只有一个指针Thing,不应该吗?
关于包括警卫的两个常见问题:
第一个问题:
为什么不包括保护我的头文件不受相互的,递归包含的警卫?我不断收到有关不存在的符号的错误,这些符号显然存在,甚至每次我写下类似的东西时都会出现更奇怪的语法错误:
"啊"
#ifndef A_H
#define A_H
#include "b.h"
...
#endif // A_H
Run Code Online (Sandbox Code Playgroud)
"BH"
#ifndef B_H
#define B_H
#include "a.h"
...
#endif // B_H
Run Code Online (Sandbox Code Playgroud)
"的main.cpp"
#include "a.h"
int main()
{
...
}
Run Code Online (Sandbox Code Playgroud)
为什么我会收到编译"main.cpp"的错误?我需要做些什么来解决我的问题?
第二个问题:
为什么不包括防止多个定义的警卫?例如,当我的项目包含两个包含相同标题的文件时,链接器有时会抱怨多次定义某个符号.例如:
"header.h"
#ifndef HEADER_H
#define HEADER_H
int f()
{
return 0;
}
#endif // HEADER_H
Run Code Online (Sandbox Code Playgroud)
"source1.cpp"
#include "header.h"
...
Run Code Online (Sandbox Code Playgroud)
"source2.cpp"
#include "header.h"
...
Run Code Online (Sandbox Code Playgroud)
为什么会这样?我需要做些什么来解决我的问题?
标头/ cpp文件中应标头的顺序是什么?显然,后续标题所需的那些应该更早,特定于类的标题应该在cpp范围内而不是标题范围,但是是否有一个集合顺序约定/最佳实践?
考虑以下两种情况(编辑只是为了完成整个问题并使其更清晰)
案例1 :(如下面正确提到的那样编译)
//B.h
#ifndef B_H
#define B_H
#include "B.h"
class A;
class B {
A obj;
public:
void printA_thruB();
};
#endif
//B.cpp
#include "B.h"
#include <iostream>
void B::printA_thruB(){
obj.printA();
}
//A.h;
#ifndef A_H
#define A_H
#include "A.h"
class A {
int a;
public:
A();
void printA();
};
#endif
//A.cpp
#include "A.h"
#include <iostream>
A::A(){
a=10;
}
void A::printA()
{
std::cout<<"A:"<<a<<std::endl;
}
//main.cpp
#include "B.h"
#include<iostream>
using namespace std;
int main()
{
B obj;
obj.printA_thruB();
}
Run Code Online (Sandbox Code Playgroud)
案例2 :(唯一的修改......没有编译错误)
//B.h
#include …Run Code Online (Sandbox Code Playgroud) 我有2个资源管理类DeviceContext,OpenGLContext都是class DisplayOpenGL.资源生命周期与之相关DisplayOpenGL.初始化看起来像这样(伪代码):
DeviceContext m_device = DeviceContext(hwnd);
m_device.SetPixelFormat();
OpenGLContext m_opengl = OpenGLContext(m_device);
Run Code Online (Sandbox Code Playgroud)
问题是调用SetPixelFormat(),因为我无法在DisplayOpenGLc'tor 的初始化列表中执行此操作:
class DisplayOpenGL {
public:
DisplayOpenGL(HWND hwnd)
: m_device(hwnd),
// <- Must call m_device.SetPixelFormat here ->
m_opengl(m_device) { };
private:
DeviceContext m_device;
OpenGLContext m_opengl;
};
Run Code Online (Sandbox Code Playgroud)
我能看到的解决方案:
m_dummy(m_device.SetPixelFormat())- 无法工作,因为SetPixelFormat()没有retval.(如果它有一个retval,你应该这样做吗?)unique_ptr<OpenGLContext> m_opengl;而不是OpenGLContext m_opengl;.m_opengl(),在c'tor体中调用SetPixelFormat()并使用m_opengl.reset(new OpenGLContext);SetPixelFormat()来自DeviceContextc'tor的 电话哪种解决方案更可取?为什么?我错过了什么?
我在Windows上使用Visual Studio 2010 Express,如果重要的话.
编辑:我最感兴趣的是在决定使用其中一种方法时所涉及的权衡.
m_dummy() 不工作,即使它会显得不优雅unique_ptr<X>对我来说很有意思 …c++ constructor initialization smart-pointers initialization-list
我有两个文件:
File1.cpp
File2.cpp
Run Code Online (Sandbox Code Playgroud)
File1是我的主类,它有main方法,File2.cpp有一个类调用ClassTwo,我想在File1.cpp中创建一个ClassTwo对象
我一起编译它们
g++ -o myfile File1.cpp File2.cpp
Run Code Online (Sandbox Code Playgroud)
但是当我尝试创造时
//创建第二类对象
ClassTwo ctwo;
Run Code Online (Sandbox Code Playgroud)
它不起作用.
错误是
ClassTwo未在此范围内声明.
这是我的main.cpp
#include <iostream>
#include <string>
using namespace std;
int main()
{
//here compile error - undeclare ClassTwo in scope.
ClassTwo ctwo;
//some codes
}
Run Code Online (Sandbox Code Playgroud)
这是我的File2.cpp
#include <iostream>
#include <string>
using namespace std;
class ClassTwo
{
private:
string myType;
public:
void setType(string);
string getType();
};
void ClassTwo::setType(string sType)
{
myType = sType;
}
void ClassTwo::getType(float fVal)
{
return myType;
}
Run Code Online (Sandbox Code Playgroud)
得到了将我的File2.cpp拆分成另一个.h文件的响应但是如果我声明一个类,我如何将它拆分成另一个.h文件,因为我需要维护变量(私有)和函数的公共和私有(公共) )如何在main方法中将ClassTwo ctwo转换为File1.cpp
所以,我遇到了一个我不太了解的有趣方法签名,它遵循以下方式:
void Initialize(std::vector< std::string > & param1, class SomeClassName * p);
Run Code Online (Sandbox Code Playgroud)
我不明白的是"class"关键字被用作参数,为什么会出现?是否有必要指明或纯粹是肤浅的?
在一个项目中,我有两个类:
// mainw.h
#include "IFr.h"
...
class mainw
{
public:
static IFr ifr;
static CSize=100;
...
};
Run Code Online (Sandbox Code Playgroud)
// IFr.h
#include "mainw.h"
...
class IFr
{
public float[mainw::CSize];
};
Run Code Online (Sandbox Code Playgroud)
但我无法编译此代码,在该static IFr ifr;行收到错误.是否禁止这种交叉包含?
在我的C++项目中何时必须使用#include "myclass.h"头文件的includes()?我什么时候必须使用class(class CMyClass;)的前向声明?
我已经看到很多关于何时使用前向声明而不是包含头文件的解释,但是很少有人解释为什么这样做很重要.我见过的一些原因包括:
来自.net背景我发现标题管理令人沮丧.我有这种感觉我需要掌握前向声明,但到目前为止我一直在报废.
为什么编译器不能为我工作并使用一种机制(包括)找出我的依赖关系?
前向声明如何加速编译,因为在某些时候引用的对象需要编译?
我可以购买降低复杂性的论据,但这样做的实际例子是什么呢?
c++ ×10
header-files ×3
class ×2
include ×2
c++-faq ×1
c++11 ×1
constructor ×1
header ×1
static ×1
stl ×1
unique-ptr ×1