【问题标题】:Why does compiler tries to pass a pointer to reference rather than pointer in this code snippet?为什么编译器会尝试将指针传递给引用而不是此代码片段中的指针?
【发布时间】:2012-04-23 10:25:28
【问题描述】:

我有 5 个文件:

  • ExecutionStrategyInterface.h
  • ExecutorInterface.h
  • TaskCollectionInterface.h
  • TaskExecutor.h
  • TaskExecutor.cpp

TaskExecutor 实现了以下成员方法:

void TaskExecutor::execute(TaskCollectionInterface* tci, const ExecutionStrategyInterface& es) {
    es.execute(tci);
}

在编译时,编译器使用指向引用的指针类型参数调用成员方法
(即:mylib::core::TaskCollectionInterface*&)。

TaskExecutor.cpp: In member function ‘virtual void mylib::core::TaskExecutor::execute(mylib::core::TaskCollectionInterface*, const mylib::core::ExecutionStrategyInterface&)’:
TaskExecutor.cpp:16: error: no matching function for call to ‘mylib::core::ExecutionStrategyInterface::execute(mylib::core::TaskCollectionInterface*&) const’
./././ExecutionStrategyInterface.h:24: note: candidates are: virtual void mylib::core::ExecutionStrategyInterface::execute(TaskCollectionInterface*) const
make: *** [TaskExecutor.o] Error 1

谁能解释一下这里发生了什么?


类:

ExecutionStrategyInterface.h

#ifndef _EXECUTIONSTRATEGYINTERFACE_H_
#define _EXECUTIONSTRATEGYINTERFACE_H_

class TaskCollectionInterface;

namespace mylib { namespace core {

/**
 *  Interface for executing a strategy.
 */
class ExecutionStrategyInterface {
 public:
    /**
     * Executes a strategy
     */
    virtual void execute(TaskCollectionInterface* tci) const = 0;
};

}} // namespaces

#endif // _EXECUTIONSTRATEGYINTERFACE_H_

TaskCollectionInterface.h

#ifndef _TASKCOLLECTIONINTERFACE_H_
#define _TASKCOLLECTIONINTERFACE_H_

#include "./ExecutionStrategyInterface.h"

namespace mylib { namespace core {

/**
 *  Interface for a collection of tasks.
 */
class TaskCollectionInterface {
 public:
    ~TaskCollectionInterface();
};

}} // namespaces

#endif // _TASKCOLLECTIONINTERFACE_H_

ExecutorInterface.h

#ifndef _EXECUTORINTERFACE_H_
#define _EXECUTORINTERFACE_H_

class ExecutionStrategyInterface;
class TaskCollectionInterface;

#include "./ExecutionStrategyInterface.h"
#include "./TaskCollectionInterface.h"

namespace mylib { namespace core {

/**
 *  Interface for an executor.
 */
class ExecutorInterface {
 public:
    virtual void execute(TaskCollectionInterface* tci, const ExecutionStrategyInterface& es) = 0;
    ~ExecutorInterface();
};

}} // namespaces

#endif // _EXECUTORINTERFACE_H_

TaskExecutor.h

#ifndef _TASKEXECUTOR_H_
#define _TASKEXECUTOR_H_

#include "./ExecutorInterface.h"

class TaskCollectionInterface;
class ExecutionStrategyInterface;

namespace mylib { namespace core {

/**
 *  Task Runner.
 */
class TaskExecutor: public ExecutorInterface {
 public:
    virtual void execute(TaskCollectionInterface* tci, const ExecutionStrategyInterface& es) = 0;
};

}} // namespaces

#endif // _TASKEXECUTOR_H_

TaskExecutor.cpp

#include "./TaskExecutor.h"
#include "./ExecutionStrategyInterface.h"
#include "./TaskCollectionInterface.h"

namespace mylib { namespace core {

void TaskExecutor::execute(TaskCollectionInterface* tci, const ExecutionStrategyInterface& es) {
    es.execute(tci);
}

}} // namespaces

【问题讨论】:

    标签: c++ inheritance pointers virtual pass-by-reference


    【解决方案1】:

    当 gcc 显示 type& 时,它只是表示您正在传递一个左值的简写,以便您知道采用非常量引用的函数是可行的候选者。

    您遇到的问题是您已将方法声明为采用::TaskCollectionInterface,但错误消息表明您正在尝试传递::mylib::core::TaskCollectionInterface

    您在 TaskCollectionInterface.h 中有一个 ::mylib::core::TaskCollectionInterface 声明,它掩盖了命名空间 mylib::core::TaskCollectionInterface 的声明。

    【讨论】:

      【解决方案2】:

      这很令人困惑,因为您在命名空间之外前向声明该类,因此您最终会得到两个具有相同名称的不同类。你会想要这样的东西:

      namespace mylib {
        namespace core {
          class TaskCollectionInterface;
          class ExecutionStrategyInterface {
            .
            .
            .
          };
        }
      }
      

      按照您现在的方式,您的 execute 方法使用指向 ::TaskCollectionInterface 而不是 mylib::core::TaskCollectionInterface 的指针。

      【讨论】:

        【解决方案3】:

        这是因为您将指针 TaskCollectionInterface* tci 传递给 ExecutionStrategyInterface::execute 方法,而它需要一个引用。因此,在将指针传递给该函数时,您必须取消引用该指针:

        void TaskExecutor::execute(TaskCollectionInterface* tci, const ExecutionStrategyInterface& es) {
            es.execute(*tci);
        }
        

        【讨论】:

          猜你喜欢
          • 2017-05-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多