English 中文(简体)
同时接受指针和引用的C++函数
原标题:
  • 时间:2009-04-10 14:42:08
  •  标签:

我正在用C++编写一个库,并且有一些可以与模块一起使用的函数。示例如下:

void connect(Module *a, Module *b);

问题是,如果接受的函数也引用(一些模块可能在堆栈上分配,一些在堆上分配,所有的&;s和*s很快就会变得无聊和混乱),有时会很方便。

现在我有了内联函数,它接受引用,将它们转换为指针,并调用原始函数。

inline void connect(Module &a, Module &b){
    connect(&a, &b);
}

我不太喜欢这个解决方案,因为对于更多的几个函数来说,它会产生大量的代码来编写、读取、编译。。。

我们正在考虑的另一件事是添加Module::operator Module*(),它将返回this

你对此有什么想法?难道没有任何我错过的巨大失败的可能性吗?

谢谢

最佳回答

为什么不直接用调用函数

connect(&a, &b);

就像在内联函数中一样,每当你必须用引用来调用它时?这非常清楚地表明,函数采用指针,而ab不是指针。你只需要再键入两个字符。

问题回答

任何时候使用运算符重载,都会增加发生大规模失败的可能性。问题是知道你不是说*是标准的指针运算符,但有人天真地阅读了你的代码却不是。

最好的解决方案是回过头来重构/重新思考代码,这样就不需要两个接口来执行相同的操作,

我不确定这在您的情况下是否是个好主意,但一般来说,您可以使用参数适配器:

struct ModulePtrOrRef
{
  Module * m_p;
  Module(Module * p) : m_p(p) {}
  Module(Module & p) : m_p(&p) {}
}

void connect(ModulePtrOrRef a, ModulePtrOrRef b)
{
  connect_impl(a.m_p, b.m_p);
}

正如您所观察到的,您可以重载函数以获取指针或引用,但我会出于方便而拒绝这样做,并坚持使用一个函数——这就是所有主要库的工作方式。

在该函数中使用哪种参数类型?这取决于我个人的指导方针:

  • 如果NULL对象有意义,请使用指针。

  • 如果常见的用例是传递的对象通常是动态创建的,那么就使用指针。

  • 如果实现在内部使用指针,请使用指针。

  • 否则,请使用引用。

我总是遵循谷歌C++风格指南中列出的惯例:

http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Reference_Arguments

基本上说只使用const&;,以及*其他一切。我认为这有助于非常清楚哪些参数是不能修改的输入(const&;s),哪些内容将被修改(*s)。如果你遵循这样的惯例,你可以避免挖掘源代码。

指针真的一点也不坏,所以没有理由回避它们。事实上,大多数时候这只意味着使用“->;”而不是“.”来取消引用,这看起来更酷,非常值得写更清晰的代码。

我很不愿意做这样的事情——这可能是一个令人困惑的界面。

一般来说,我更喜欢使用常量引用的接口,但如果传入的对象将被修改,我倾向于更喜欢指针而不是非常量引用,因为它会向接口的用户指示传入的对象可能会被修改。

之所以需要两个函数,是因为指向Module的指针与指向Module的引用从根本上不同。这是无法回避的。

对我来说,指针很糟糕。总是只有当你需要某个东西的地址而不是对某个事物的引用时,才使用它们。而且很少需要对象的实际地址。我会做以下事情:

  1. Turn the pointer-based function into a reference-based function.
  2. Stop using pointers where unnecessary. You certainly should avoid having pointers and references.

此外,您可能需要调查constness。

我会避免在公共API中内联。

常量&;在可能的情况下比&;或*

我不知道这些东西是如何联系在一起的,也不知道a和b之间有什么关系

void connect(Module *a, Module *b);

将模块接口重新安排得更明确有意义吗

Module a;
a.connectOutput(b);

命名参数有助于上下文;)





相关问题
热门标签