对象之间的差异->function()和object.function()
Difference between object->function() and object.function() in C++
有人能解释一下做之类的事情之间的区别吗
a->height();
和
a.height();
真的有区别吗?
在第一个示例中,a是指向对象的指针,在第二个示例中是对象本身(或对对象的引用)。在最低层次上,两者之间没有明显的区别。
这是一个奇怪的问题,假设我们谈论的是内置的->
。这听起来有点像"锤子和苹果有什么区别"。通常,当两种变体至少在某种程度上可互换时,就会出现关于"差异"的问题,两者同时适用。因此,人们会询问"差异"来决定使用哪种变体。这里的情况并非如此。
a->height()
和a.height()
不能同时有效。根据a
的类型,两者中只有一个是有效的。也就是说,你无法选择使用哪个版本。如果左侧是指向对象的指针,则第一个(带有->
)适用。第二个(只有.
)仅适用于左侧为对象值本身的情况。所以,这就是它的全部。
->
只是一元*
和.
的组合的简写,这意味着当a
是指针时,a->height()
等效于(*a).height()
。因此,一个更合理的问题是a->height()
和(*a).height()
之间的差异。答案是:没有区别(同样,只要我们考虑内置的->
)
它基本上可以归结为您如何声明"a"。如果你这样做:
SomeClass a;
那么"a"本身就是一个对象,您可以使用"."来引用其成员。
如果你这样做:
SomeClass * a;
a = [some expression that produces a pointer to a SomeClass object];
则"a"是指向对象的指针,而不是对象本身。然后使用"->"表示法。
(上述规则有一些潜在的例外,但大多数人都不会遇到。)
还值得一提的是,一些对象(如智能指针)支持这两种符号。在这种情况下,第一个将引用指针所指向的对象,第二个将引用智能指针本身。
operator->
后面跟着一个函数调用,将导致返回的指针被取消引用,并在结果对象上调用函数。简而言之,a->foo()
是(*a).foo()
的简写。
除了a->foo()
需要a
作为定义foo
的类的指针这一正确答案之外,一个人为的例子可能会告诉我们一些不同的东西:
struct xC {
struct Member {
void foo(){printf("xC::Member::foon");};
};
Member a;
Member* operator->() { return &a; }
// following function doesn't really make sense.
void foo() { printf("xC::foon");};
};
int main(){
xC x;
x.foo(); // prints "xC::foo".
x->foo();// prints "xC::Member::foo"
}
在智能指针和stl迭代器的上下文中,您经常会看到这些类型的operator->
定义。在这种情况下,定义确实遵循了Stroustrup的指导方针,不要像我的例子那样滥用它来做一些违反直觉的事情,而是让定义类像"指向"某个对象一样可用。
假设a
是指向某个对象的指针,则:
此:
a->height();
只是的简写
(*a).height();
它允许您通过指针而不仅仅是普通对象(或引用)来调用方法
实际上,您不需要使用->版本,但当您将几个调用链接到一起时,它的用处就显而易见了。
person->body()->arm(right)->hand()->finger(index)->ring()->activate();
如果你写这个长手,它是:
(*(*(*(*(*(*person).body()).arm(right)).hand()).finger(index)).ring()).activate();
很难将取消引用(*
)与正在取消引用的指针关联起来。而第一个版本->左边的东西是一个指针,右边的东西是指针被取消引用后的对象部分。
正如其他人所说,如果你谈论的是指针的去引用,那么差异不会太大。然而,更重要的是,如果a
是一个实例或引用,并且定义了operator->
函数,那么您可能会看到非常不同的行为。a.name()
会调用a的name()
函数,而a->name()
可能会调用其他类型的name()
函数以及该类决定要做的任何其他工作(这是一个返回指针的函数调用,因此"邪恶"类只要返回有效指针,就可以做它想做的任何事情)。这主要用于智能指针,但在语言中不能保证这一点。
这一切都可以归结为代码本身的可读性和速度。在汇编程序的最低级别,它可以归结为推/拉堆栈。在当今拥有快速计算机/MCU的现实生活中,这并不重要。这是你使用的编程风格。两种方法都可以,但不要混合使用。这可能会让其他程序员很难阅读。
- "error: no matching function for call to"构造函数错误
- 调用专用模板时出错"no matching function for call to [...]"
- 库函数需要一个 std::function<void(void)>,如何传入类函数?
- Confusion: decltype vs std::function
- 为什么 std::function 可以作为 std::not2 的参数?
- 'max'匹配'std::function<const int &(const int &, const int &)>'无过载
- 传递给std::function template的template参数究竟代表什么
- 将带有unique_ptr的可变 lambda 传递给 const&std::function
- 使用 object 中的方法调用带有 std::bind 和 std::function.target 的 C 样式函数
- "Called Object Type is Not a Function or Pointer" 与 typedef 和类
- C++线程"Call to non-static member function without an object argument"
- "Called object 'int' is not a function or a function pointer"错误
- 为什么委托或闭包通常被称为真正的"object-oriented function pointers"?
- C++常见问题 32.8 "pass an object of a C++ class to/from a C function"问题
- "Cannot call member function ... without object"在未评估的上下文中 - GCC 错误?
- 如何为静态成员编写std::is_member_{object,function}_pointer
- 如何传递lambda, function object或std::function作为模板参数并控制它们的参数
- C++11 模板错误消息:"cannot call member function without object"
- `print` function for an object with two different constructo
- 对象之间的差异->function()和object.function()