【问题标题】:is there a way to skip class name while define a class member function in c++?有没有办法在 C++ 中定义类成员函数时跳过类名?
【发布时间】:2015-07-27 05:38:29
【问题描述】:

例如,我在 dog.h 中声明了一个名为 Dog 的类:

class Dog {
public:
    void bark();
private:
    int count;
}

有什么办法可以在 dog.cpp 中写下以下代码:

void bark() {
   printf("count: %d", count);
}

代替:

void Dog::bark() {
   printf("count: %d", count);
}

如果我有大量应该定义的类函数,这将有助于节省时间。 (我可以将函数定义复制粘贴到 .h 文件中,而无需每次都删除类名。)

在objective-c代码中,我可以在.m(它的作用就像.cpp)文件中添加一个“@implementation ... @end”范围,然后我可以像这样编写函数:

in dog.h:
- (void) bark;

in dog.m:
@implementation Dog
- (void) bark {
    printf("count: %d", count);
}
@end

所以我认为c++中可能有类似的方式。

你看,我可以将.m文件中的函数定义代码复制到.h文件中,只需要加一个“;”行尾的符号。如果类函数是私有函数,我什至不需要在 .h 文件中声明它。所以我觉得objective-c在声明类的时候比c++方便。

【问题讨论】:

  • 拥有@implementation ... @end 意味着您不能可靠地识别非成员函数而不搜索回文件的顶部(或者可能是以前的@end - 如果有的话- 或关闭命名空间或任何其他实现无法跨越的东西)。我想同样的批评也可以针对命名空间。
  • 您提到您只想复制粘贴内容。你到底想做什么?您可能还可以使用其他技术来避免代码重复。

标签: c++ objective-c function class


【解决方案1】:

有什么方法可以让我在 dog.cpp 中编写以下代码?

不,你不能那样做。在类定义之外定义成员函数时必须使用类名。

来自 C++11 标准:

9.3 成员函数

5 如果成员函数的定义在词法上超出其类定义,则成员函数名称应使用:: 运算符由其类名限定。

【讨论】:

  • @firestoke ,由 R Sahu 回答:“不,你不能那样做”
  • 嗯...这真的让我很烦。我也写了很长时间的objective-c代码。我可以通过在 .m 文件中使用“@implementation ... @end”在objective-c 代码中编写没有类名前缀的成员函数。所以我认为c++中可能有类似的方式...
  • 是的。人们在和你开玩笑
  • @firestoke,C++ 社区一定不会认为这是一个大问题 :) 就个人而言,它使代码更具可读性,ClassName:: 附加到实现中。此外,从长远来看,与维护代码所需的时间相比,将ClassName:: 添加到成员函数实现所需的时间会逐渐减少。
  • @firestoke:尝试按照语言希望的方式编写代码是件好事。想象一下有人问'有没有办法在法语中否定一个句子没有烦人的ne ... pas'?
【解决方案2】:

简单模式

在您的 cpp 文件中,您可以使用以下模式:

#include "dog.h"

#define _C Dog::

void _C bark () {
...
}

void _C foo () {
...
}

#undef _C

_C 的使用对于任何 TU 都是相同的。

更精细的模式

概念:直接在类定义中生成成员实现代码。 文件结构模式:

  1. 名为dog.h的常规头文件
  2. 包含方法实现的头文件 包括,命名为“dog.hxx”
  3. 定义了特殊宏IMPLEMENT_API时包含“dog.h”的cpp文件

常规头文件dog.h:

class Dog {
public:
    void bark();
private:
    int count;
#ifdef IMPLEMENT_API
#include "dog.hxx"
#endif
}

dog.hxx 文件:

void bark() {
   printf("count: %d", count);
}

void foo() {
   printf("foo: %d", count+1);
}

dog.cpp 文件:

#define IMPLEMENT_API
#include "dog.h"

在更复杂的情况下,一个 TU 可以用于第二种模式的多个实例,例如下面的 animals.cpp 文件。
animals.cpp 文件:

#define IMPLEMENT_API
#include "cat.h"
#include "dog.h"

另一个类cat 使用与IMPLEMENT_API 宏类似的语句定义为dog。 在包括dog.hcat.h 的另一个文件中,将仅生成声明,因为IMPLEMENT_API 宏必须仅在像dog.cppanimals.cpp 这样的TU 中定义。

优点:dog.hxxcat.hxx 文件使用其类的上下文和命名空间,允许省略每个成员定义的类的完全限定名。

注意:如果编译器不允许同时拥有成员声明和成员定义,则成员声明应使用模式#ifdef IMPLEMENT_API <member definitions> #else <member declarations> #endif 包装。

【讨论】:

  • 这样更好。我可以将代码复制到其他文件中并使用它,只需将_C定义修改为不同的类名。但是当我复制它时,我仍然需要删除 .h 中的“_C”。我是一个非常懒惰的开发人员,哈哈。 (我厌倦了在重复的不必要的例程中浪费时间。)
  • @firestoke I still need to delete "_C" in the .h when I copy it. 对于 PCRE 兼容的编辑器,以下可能有用:s/@implementation (\w+)/#define _C $1::/g
  • @firestoke I still need to delete "_C" in the .h when I copy it. 使用第二种模式你不会:-)
【解决方案3】:

抱歉迟到了。我不怎么到处走动。 ;)

您不需要 .cpp 文件来定义您的函数。您可以在类定义中执行此操作。事实上,如果你想内联,你必须这样做。

大多数人似乎都迷恋 .cpp。 ;) 我将几乎所有的函数都放在类定义中。我的大多数课程都没有 .cpp 文件,但有时它们是必需的。

瞧!没有 Dog:: 也没有 .cpp 文件。enter code hereclass Dog {

public:
    void bark() {
    printf("count: %d", count);
    }
private:
    int count;
}

【讨论】:

  • 其实这是拜物教(你的话)。一旦你说超过 10 个函数与数据混合,并为所有函数提供定义,那么上帝会帮助你。将它定义在一个地方的风格是多么混乱。在头文件中,我想知道一个类接口,而不是实现。这就是 .cpp 的用途,如果我想看一个巨大的类,我根本不期望定义,因为它不应该存在
【解决方案4】:

class 中将函数标记为friend

class Dog {
friend void bark (Dog &); /// mark as friend

private:
int count = 22;
};

有了这个你可以访问class Dog中的一些private成员

void bark (Dog &d1)
{
std::cout << d1.count << std::endl;
}

【讨论】:

  • 看起来像。它确实做了OP想要的,有点。不过需要大量额外的击键。
  • 它当然不符合 OP 的要求。问题是关于 member 函数的。
  • @juanchopanza 你错过了它的幽默。 OP 不想输入dog::。此解决方案要求 OP 键入两次 friendDog &amp; 一个变量名,然后在所有成员访问前加上该变量名。不管它是否是好的 C++,这都会变得更加不方便。
  • @user4581301 好笑!我笑得差点从椅子上摔下来。
  • 我明白了。如果他编写了一个 dll,将其注入 IDE,绕过按下“编译按钮”时调用的函数,检查项目中的所有文件,将 dog:: 或任何类名放在所有函数的前面等等并调用将编译代码的原始函数,这将为他节省一些时间!告诉你我明白了
猜你喜欢
  • 2019-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多