是否可以避免在实现文件中重复类名?

时间:2012-06-04 19:36:30

标签: c++ class syntax

有没有办法避免实现文件中的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(){}

8 个答案:

答案 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文件,但不要在头文件上拆分类。