有没有办法避免实现文件中的Graph::
重复,但仍然将类拆分为标头+实现?如:
标题文件:
#ifndef Graph_H
#define Graph_H
class Graph {
public:
Graph(int n);
void printGraph();
void addEdge();
void removeEdge();
};
#endif
实施档案:
Graph::Graph(int n){}
void Graph::printGraph(){}
void Graph::addEdge(){}
void Graph::removeEdge(){}
答案 0 :(得分:12)
如果你想避免在printGraph,addEdge等前面输入“Graph ::”,那么答案是“不”,不幸的是。类似于C#的“部分类”功能在C ++中是不可访问的,任何类的名称(如“Graph”)都不是命名空间,它是一个范围。
答案 1 :(得分:9)
我猜这是为了避免大量“不必要的打字”。可悲的是,没有办法摆脱范围(正如许多其他答案告诉你的那样)然而我个人所做的是用我所有的函数原型定义好的行,然后复制/粘贴到实现文件然后ctrl-c剪辑板上的ClassName ::并使用ctrl-v运行该行。
答案 2 :(得分:5)
不,没有。至少不是直接的。您可以选择预处理器技巧,但不要这样做。
#define IMPL Graph::
IMPL Graph(int n){}
void IMPL printGraph(){}
void IMPL addEdge(){}
void IMPL removeEdge(){}
此外,您甚至不应该想要这样做。重点是什么。除了它是一个C ++规则,它还会让你知道你实际上正在实现一个成员函数。
答案 3 :(得分:2)
不,没有办法避免它。否则,您如何知道给定的函数定义是用于类函数还是用于静态函数?
答案 4 :(得分:2)
如果您询问是否可以定义成员函数(例如Graph::printGraph
而未指定类名称限定条件),则答案为否,而不是您想要的方式。这在C ++中是不可能的:
实施档案:
void printEdge(){};
以上编译就好了,但它不会做你想要的。它不会在Graph
类中使用相同的名称定义成员函数。相反,它将声明并定义一个名为printEdge
的新自由函数。
这是好的和正确的,如果你的观点有点痛苦,因为你可能想要两个具有相同名称但在不同范围内的函数。考虑:
// Header File
class A
{
void foo();
};
class B
{
void foo();
};
void foo();
// Implementation File
void foo()
{
}
该定义适用于哪个范围? C ++不会限制您在不同的范围内使用相同名称的不同函数,因此您必须告诉编译器您正在定义哪些函数。
答案 5 :(得分:1)
//yes it is possible using preprocessor like this:
#define $ ClassName //in .cpp
void $::Method1()
{
}
//or like this: in the header .h:
#undef $
#define $ ClassName'
// but you have to include the class header in last #include in your .cpp:
#include "truc.h"
#include "bidule.h" ...
#include "classname.h"
void $::Method() { }
//i was using also
#define $$ BaseClass
//with single inheritance than i can do this:
void $::Method()
{
$$::Method(); //call base class method
}
//but with a typedef defined into class like this it's better to do this:
class Derived : Base
{
typedef Base $$;
}
答案 6 :(得分:1)
一个选项是 <Label
Text="Some text">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</Label.GestureRecognizers>
</Label>
。如果您的cpp文件中的方法定义永远不会using
d,那么#include
是安全的(不会影响其他文件):
foo.h:
using
foo.cpp:
class FooLongNameSpecialisationsParamaters
{
int x_;
public:
int Get () const;
void Set (int);
};
main.cpp:
#include "foo.h"
using Foo = FooLongNameSpecialisationsParamaters;
int Foo::Get () const
{
return x_;
}
void Foo::Set (int x)
{
x_ = x;
}
答案 7 :(得分:0)
简单的答案:您可以拆分c ++文件,但不能拆分头文件。
原因很简单。每当编译器需要编译构造函数时,它需要确切地知道需要为这样的对象分配多少内存。
例如:
class Foo {
double bar; //8 bytes
int goo; //4 bytes
}
'new Foo()'需要分配12个字节的内存。但是如果你被允许将你的类定义扩展到多个文件(即拆分头文件),你很容易弄清楚这一点。你的编译器永远不会知道你是否已经告诉了它关于这个类的一切,或者你是否已经告诉了它。代码中的不同位置可能具有不同的类定义,从而导致分段错误或极其隐密的编译器错误。
例如:
h1.h:
class Foo {
double bar; //8 bytes
int goo; //4 bytes
}
h2.h: #include“h1.h”
class Foo {
double goo; //8 bytes
}// we extend foo with a double.
foo1.cpp:
#include "foo1.h"
Foo *makeFoo() {
return new Foo();
}
foo2.cpp:
#include "foo2.h"
void cleanupFoo(Foo *foo) {
delete foo;
}
foo1.h:
#include "h1.h"
Foo *makeFoo();
foo2.h:
#include "h1.h"
#include "h2.h"
void cleanupFoo(Foo *foo)
main.cpp中:
#include foo1.h
#include foo2.h
void main() {
Foo *foo = makeFoo();
cleanupFoo(foo);
}
现在非常仔细地检查如果你首先将main.cpp编译为main.o,然后将foo1.cpp编译为foo1.o并将foo2.cpp编译为foo2.o,最后将所有这些链接在一起。这应该编译,但是makeFoo()会分配其他东西,然后释放cleanupFoo()。
所以你有它,随意拆分.cpp文件,但不要在头文件上拆分类。