【问题标题】:Functions with const arguments and Overloading带有 const 参数和重载的函数
【发布时间】:2011-04-10 13:40:58
【问题描述】:

正在尝试the stackeroverflow qn,所以它让我思考为什么不重载函数,我想出了一个稍微不同的代码,但它说函数不能重载。我的问题是为什么?还是有其他方法?

 #include <iostream>
 using std::cout;

 class Test {
         public:
         Test(){ }
         int foo (const int) const;
         int foo (int );
 };

 int main ()
 {
         Test obj;
         Test const obj1;
         int variable=0;
     do{
         obj.foo(3);        // Call the const function 
          obj.foo(variable); // Want to make it call the non const function 
         variable++;
             usleep (2000000);
        }while(1);
 }

 int Test::foo(int a)
 {
    cout<<"NON CONST"<<std::endl;
    a++;
    return a;
 }

 int Test::foo (const int a) const
 {
    cout<<"CONST"<<std::endl;
    return a;
 }

【问题讨论】:

  • “它说函数不能重载”是什么意思。你得到一个编译错误?什么错误?或者它只是行为,说它?如果是行为,那么你的结论是错误的,我担心。您实际上已成功重载。问题是,该决议是基于不同的事情做出的,你认为它应该是。
  • @Maciej..是的,这是一个编译错误..我已经过了这一点..查看后续线程...stackoverflow.com/questions/3683881/…

标签: c++ class constants overloading


【解决方案1】:

您不能仅基于非指针、非引用类型的常量来重载。

例如,假设您是编译器。 面对线:

 cout <<obj.foo(3);

你会调用哪个函数?

当您通过值传递时,值会以任何一种方式被复制。参数上的 const 只与函数定义有关。

【讨论】:

  • 我的想法是让它调用 foo (const int a) 函数..所以我真正的问题是如何让它调用 const 函数(并使其可编译)
  • @MrProg:如上所述,该语言不支持它。如果您真的要这样做,请执行 foo(const int&) 和 foo(int&) 之类的操作。这会做你想做的事,尽管非 const 版本将能够更改传入的变量。
  • +1 表示“非指针的常量,非引用类型”。函数可以在指针和引用类型的常量上重载。
  • @user3665224 指针类型的常量还是它指向的类型? (例如 const int */int const *int * const
【解决方案2】:

§13.1 标准讨论了不能重载状态的声明 -

不同的参数声明 仅在存在或不存在的情况下 const 和/或 volatile 是等价的。 即 const 和 volatile 每个参数的类型说明符 类型被忽略 [...]

只有 const 和 volatile 最外层的类型说明符 参数类型规范 以这种方式被忽略;常量和 volatile 类型说明符隐藏在 参数类型规范是 显着,可用于 区分重载函数 声明。 [...]

当确定哪个函数是 被声明、定义或调用。 “特别是,对于任何类型 T, “指向 T 的指针”、“指向 const T 的指针” 和“指向 volatile T 的指针”是 考虑不同的参数类型, 正如“对 T 的引用”、“对 const T”和“对 volatile 的引用 T。”

编辑 2:

由于该帖子与reffered post 基本相同,除了重载函数现在是类成员函数,我试图说明一个额外的方面,这可能有助于说明不同的重载概念作为基于参数的“常量”的重载(在类范围或命名空间范围内)。然而,OP 想知道如何区分这两个重载。

在成员函数调用的情况下,成功重载它们的方法依赖于隐含的第一个参数的 cv 限定,如图所示。只有当用于调用重载成员函数的对象表达式也是 const 时,才能调用“const”成员函数。当使用非 const 对象表达式调用重载的成员函数调用时,首选非 const 版本,因为它是完全匹配的(对 const 成员函数重载的调用将需要对第一个隐含参数进行 cv 限定)

#include <iostream> 
using std::cout; 

class Test { 
        public: 
        Test(){}
        int foo (const int) const; 
        int foo (int ); 
}; 

int main () 
{ 
        Test obj;
        Test const objc;  // const object
        obj.foo(3);       // calls non const overload, object expression obj is non const
        objc.foo(3);      // calls const overload, object expression objc is const
} 

int Test::foo(int a) 
{ 
   a++; 
   return a; 
} 

int Test::foo (const int a) const
{ 
   return a; 
} 

【讨论】:

  • 嘿。我喜欢该标准使用极具技术性的术语“隐藏”来描述非顶级 cv 限定符。 :-P
  • 我确实看到了链接线程中提到的标准......因此问题是“或者还有其他方法吗?”使其调用 const 函数
  • @James McNellis:如果这令人困惑,我完全赞成删除这篇文章。
  • @MrProg:我猜标准中的引用不清楚。这基本上意味着void foo(int);void foo(const int) 是相同的签名,在这两种情况下,参数都将被复制并且调用者整数不会被修改。 const 的区别只影响函数的定义,在第二种情况下,定义不能修改它自己的值副本。
  • @MrProg:如果出于某种模糊的原因您希望int x; const int y; f(x); f(y); 调用不同的函数(即使在这两种情况下该函数都不会修改xy,您可以使用引用:@987654329 @ 但这将允许第一个版本修改作为参数传递的x,因此在语义上不等同于您的初始代码。我真的看不到您希望通过值传递但仍然调用不同的用例如果参数是 const/non-const,则重载。
【解决方案3】:

正如另一个问题的答案所解释的,两个foos 没有区别,因为它们具有等效的参数定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    • 2012-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多