编译器生成的方法调用错误

时间:2013-06-24 20:30:13

标签: c++

Windows 7 cygwin 1.7.20 gcc 4.5.3

我的一个类中有一个方法,enqueue(const PTR X,const void * operation),当试图调用它时,实际调用另一个方法,enqueue(bool X)'当原始方法更改为,enqueue(const PTR X)正确调用它。我无法弄清楚我可能做了什么来引发这种行为。代码是可编译的。

/****** SlipDef.h ******/

#ifndef SLIPDEF_H
#define SLIPDEF_H
# include <string>
# include "SlipPointer.h"
using namespace std;
namespace slip {
    typedef unsigned char   UCHAR;
    typedef signed   char   CHAR;
    typedef unsigned short  USHORT;
    typedef signed   short  SHORT;
    typedef unsigned int    UINT;
    typedef signed   int    INT;
    typedef unsigned long   ULONG;
    typedef signed   long   LONG;
    typedef float           FLOAT;
    typedef double          DOUBLE;
    typedef SlipPointer *   PTR;
    typedef SlipPointer *   STRING;
} // namespace slip
#endif  /* SLIPDEF_H */
/****** SlipHeader.h ******/

#ifndef _SLIPHEADER_H
#define _SLIPHEADER_H
# include <string>
# include "SlipDef.h"
namespace slip {

   class SlipHeader {
   public:
      SlipHeader&       enqueue(SlipHeader& X);
      SlipHeader&       enqueue(bool X);
      SlipHeader&       enqueue(UCHAR X);
      SlipHeader&       enqueue(CHAR X);
      SlipHeader&       enqueue(ULONG X);
      SlipHeader&       enqueue(LONG X);
      SlipHeader&       enqueue(DOUBLE X);
      SlipHeader&       enqueue(const PTR X, const void* operation);
      SlipHeader&       enqueue(const string& X, bool constFlag = false);
      SlipHeader&       enqueue(const string* X, bool constFlag = false);
    };
};
#endif  /* SLIPHEADER_H */

/****** SlipPointer.h ******/

#ifndef SLIPPOINTER_H
#define SLIPPOINTER_H
using namespace std;
namespace slip {

   class SlipPointer { 
   public:
   };
} // namespace slip
#endif  /* SLIPPOINTER_H */

/****** TheOtherHeader.h ******/

#ifndef _THEOTHERHEADER_H
#define _THEOTHERHEADER_H
# include <string>
# include "SlipDef.h"
namespace slip {

   class TheOtherHeader {
   public:
      TheOtherHeader&   enqueue(TheOtherHeader& X);
      TheOtherHeader&   enqueue(bool X);
      TheOtherHeader&   enqueue(UCHAR X);
      TheOtherHeader&   enqueue(CHAR X);
      TheOtherHeader&   enqueue(ULONG X);
      TheOtherHeader&   enqueue(LONG X);
      TheOtherHeader&   enqueue(DOUBLE X);
      TheOtherHeader&   enqueue(const PTR X);
      TheOtherHeader&   enqueue(const string& X, bool constFlag = false);
      TheOtherHeader&   enqueue(const string* X, bool constFlag = false);
    };
};
#endif  /* _THEOTHERHEADER_H */

/****** main.cpp ******/

# include "SlipHeader.h"
#include "TheOtherHeader.h"
# include <string>
# include <iostream>
using namespace std;
using namespace slip;

int main(int argc, char** argv) {
   SlipPointer*    ptr    = new SlipPointer();
   SlipHeader*     header = new SlipHeader();
   TheOtherHeader* theOtherHeader = new TheOtherHeader();
   header->enqueue(ptr);
   theOtherHeader->enqueue(ptr);
return 0;
}

/****** SlipHeader.cpp ******/

# include <string>
# include <iostream>
# include "SlipDef.h"
# include "SlipHeader.h"
namespace slip {
   static void* ptrOP;
   SlipHeader& SlipHeader::enqueue(SlipHeader& X) { cout << "enqueue(SlipHeader& X) wrong answer" << endl; return *new SlipHeader();}
   SlipHeader& SlipHeader::enqueue(bool X)      { cout << "enqueue(bool X) wrong answer" << endl;      return *new SlipHeader();}
   SlipHeader& SlipHeader::enqueue(UCHAR X)     { cout << "enqueue(UCHAR X) wrong answer" << endl;     return *new SlipHeader();}
   SlipHeader& SlipHeader::enqueue(CHAR X)      { cout << "enqueue(CHAR X) wrong answer" << endl;      return *new SlipHeader();}
   SlipHeader& SlipHeader::enqueue(ULONG X)     { cout << "enqueue(ULONG X) wrong answer" << endl;     return *new SlipHeader();}
   SlipHeader& SlipHeader::enqueue(LONG X)      { cout << "enqueue(LONG X) wrong answer" << endl;      return *new SlipHeader();}
   SlipHeader& SlipHeader::enqueue(DOUBLE X)    { cout << "enqueue(DOUBLE X) wrong answer" << endl;    return *new SlipHeader();}
   SlipHeader& SlipHeader::enqueue(const PTR X, const void* operation = ptrOP) {
      cout << "enqueue(PTR X) right answer" << endl; return *new SlipHeader();
   };
   SlipHeader& SlipHeader::enqueue(const string& X, bool constFlag) { cout << "enqueue(string& X) wrong answer" << endl; return *new SlipHeader();}
   SlipHeader& SlipHeader::enqueue(const string* X, bool constFlag) { cout << "enqueue(string* X) wrong answer" << endl; return *new SlipHeader();}
};
/****** TheOtherHeader.cpp ******/

# include <string>
# include <iostream>
# include "SlipDef.h"
# include "TheOtherHeader.h"
namespace slip {
   static void* ptrOP;
   TheOtherHeader& TheOtherHeader::enqueue(TheOtherHeader& X) { cout << "enqueue(TheOtherHeader& X) wrong answer" << endl; return *new TheOtherHeader();}
   TheOtherHeader& TheOtherHeader::enqueue(bool X)      { cout << "enqueue(bool X) wrong answer" << endl;      return *new TheOtherHeader();}
   TheOtherHeader& TheOtherHeader::enqueue(UCHAR X)     { cout << "enqueue(UCHAR X) wrong answer" << endl;     return *new TheOtherHeader();}
   TheOtherHeader& TheOtherHeader::enqueue(CHAR X)      { cout << "enqueue(CHAR X) wrong answer" << endl;      return *new TheOtherHeader();}
   TheOtherHeader& TheOtherHeader::enqueue(ULONG X)     { cout << "enqueue(ULONG X) wrong answer" << endl;     return *new TheOtherHeader();}
   TheOtherHeader& TheOtherHeader::enqueue(LONG X)      { cout << "enqueue(LONG X) wrong answer" << endl;      return *new TheOtherHeader();}
   TheOtherHeader& TheOtherHeader::enqueue(DOUBLE X)    { cout << "enqueue(DOUBLE X) wrong answer" << endl;    return *new TheOtherHeader();}
   TheOtherHeader& TheOtherHeader::enqueue(const PTR X) {
      cout << "enqueue(PTR X) right answer" << endl; return *new TheOtherHeader();
   };
   TheOtherHeader& TheOtherHeader::enqueue(const string& X, bool constFlag) { cout << "enqueue(string& X) wrong answer" << endl; return *new TheOtherHeader();}
   TheOtherHeader& TheOtherHeader::enqueue(const string* X, bool constFlag) { cout << "enqueue(string* X) wrong answer" << endl; return *new TheOtherHeader();}
};

2 个答案:

答案 0 :(得分:1)

您有const void* operation的默认参数。但是,您在实现中设置这些默认参数而不是标题 - 它应该是相反的方式:

// header
void f(int x=5);

// implementation
void f(int x) { }

原因很简单,如果在主代码中调用header->enqueue(ptr),编译器只知道标头给出的信息。如果标头不包含默认参数,则编译器不知道此时是否存在默认参数。

答案 1 :(得分:0)

由于您的头文件定义了这个:

SlipHeader&       enqueue(const PTR X, const void* operation);

你这样称呼它:

header->enqueue(ptr);

编译器不会将声明视为函数调用的有效匹配(您只传递一个参数,并且不为第二个参数声明默认参数),并选择一个可以使用单个调用的参数争论而不是。 为什么选择bool为什么需要更多地挖掘标准。

在函数的实际定义中为第二个参数提供默认参数的事实在编译main()时对编译器是不可见的,因此不予考虑。您应该将默认参数移动到标题中(事实上,如果您有警告,您可能会根据您现在安排的方式收到警告)。

编辑:正如aschepler在下面指出的那样,bool版本被调用的原因是它是[const] void *唯一允许的自动转换。