Компилятор VC ++ игнорирует перегруженную функцию

Вот мой код (упрощенно):

//wrapper.h
#include <play3d.h>
class wrapper
{
private:
soundengine *soundEngine;
public:
sound *playSound3D(source *source, D3DXVECTOR3 pos, bool loop=false);
};

//wrapper.cpp
sound *wrapper::playSound3D(source *source, D3DXVECTOR3 pos, bool loop)
{
return soundEngine->play3D(source, pos, loop);
};

А вот и мой полный код (по запросу). Он использует звуковой движок irrKlang:

//irrKlang.h
virtual ISound* play3D(ISoundSource* source, vec3df pos,
bool playLooped = false,
bool startPaused = false,
bool track = false,
bool enableSoundEffects = false) = 0;//the version i want

virtual ISound* play3D(const char* soundFileName, vec3df pos,
bool playLooped = false,
bool startPaused = false,
bool track = false,
E_STREAM_MODE streamMode = ESM_AUTO_DETECT,
bool enableSoundEffects = false) = 0;//the version vc++ finds//fsCore.h
#include <irrklang.h>
class fsEngine
{
private:
static fsEngine *instance;
static fsBool exists;
irrklang::ISoundEngine *soundEngine;
fsEngine();
~fsEngine();
public:
static fsEngine *getInstance()
{
if (!exists)
{
instance = new fsEngine();
exists = true;
return instance;
}
else
{
return instance;
}
};
void release()
{
exists = false;
delete instance;
soundEngine->drop();
};
public:
irrklang::ISoundSource *loadSound(fsString filename);
irrklang::ISoundSource *cloneSound(irrklang::ISoundSource *source, fsString alias=NULL);
irrklang::ISound *playSound2D(irrklang::ISoundSource *source, fsBool loop=false);
irrklang::ISound *playSound3D(irrklang::ISoundSource *source, D3DXVECTOR3 soundpos, fsBool loop=false);
};//fsCore.cpp
#include "fsCore.h"irrklang::ISound *fsEngine::playSound3D(irrklang::ISoundSource *source, D3DXVECTOR3 soundpos, bool loop)
{
return soundEngine->play3D(source, soundpos, loop);
};

Я получаю Ошибка C2664 из ниоткуда.

1>c:\users\...\documents\visual studio 2008\projects\core\fscore.cpp(20) : error C2664: 'irrklang::ISound *irrklang::ISoundEngine::play3D(const char *,irrklang::vec3df,bool,bool,bool,irrklang::E_STREAM_MODE,bool)' : cannot convert parameter 1 from 'irrklang::ISoundSource *' to 'const char *'
1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

Play3D () имеет два определения: одно, которое принимает 'const char *' в качестве аргумента 1, а другой, который принимает 'source *' в качестве аргумента 1. Intellisense указывает оба определения, но я не могу заставить экспресс-компилятор VC ++ 2008 распознать нужную мне версию. Что я могу изменить?

0

Решение

В вашем коде есть две проблемы, обе они указаны в комментариях.

# 1 от @john:

virtual ISound* play3D(ISoundSource* source,
vec3df pos,
bool playLooped = false,
bool startPaused = false,
bool track = false,
bool enableSoundEffects = false) = 0;

irrklang::ISound *fsEngine::playSound3D(irrklang::ISoundSource *source,
D3DXVECTOR3 soundpos, bool loop)
{
return soundEngine->play3D(source, soundpos, loop);
}

Звонящий передает D3DXVECTOR3, но вызываемый ожидает vec3df, Это разные типы, и нет неявного преобразования между ними, поэтому компилятор даст вам немного вид ошибки. В данном случае конкретная ошибка может немного вводить в заблуждение.

(Неважно, что оба класса имеют одинаковый размер и имеют одинаковые члены данных в одинаковом порядке. C ++ только два типа считаются равными, если они являются равны, невзирая на как они осуществляются внутри страны.)

# 2 от @Named:

Даже если D3DXVECTOR3 а также vec3df являются typedefs для того же типа, у вас есть другая проблема. Ваши два виртуальных метода имеют одно и то же имя, поэтому они являются перегрузками; и из-за того, как функция сверхпогрузка взаимодействует с виртуальнымверховая езда, Перегрузка дочернего класса фактически скрывает версию родительского класса. Пример:

struct X; struct Base                  { virtual void foo(X *); };
struct Y; struct Derived : public Base { virtual void foo(Y *); };

void f(Derived *d, X *x) { d->foo(x); }% clang++ -Wall test.cc
test.cc:2:59: warning: 'Derived::foo' hides overloaded virtual function [-Woverloaded-virtual]
struct Y; struct Derived : public Base { virtual void foo(Y *); };
^
test.cc:1:59: note: hidden overloaded virtual function 'Base::foo' declared here
struct X; struct Base                  { virtual void foo(X *); };
^
test.cc:4:39: error: cannot initialize a parameter of type 'Y *' with an lvalue of type 'X *'
void f(Derived *d, X *x) { d->foo(x); }
^
test.cc:2:66: note: passing argument to parameter here
struct Y; struct Derived : public Base { virtual void foo(Y *); };
^

Один из способов исправить это с using директива:

struct X; struct Base                  { virtual void foo(X *); };
struct Y; struct Derived : public Base { virtual void foo(Y *); using Base::foo; };

void f(Derived *d, X *x) { d->foo(x); }

Это повторно добавляет Base::foo в список кандидатов, когда мы смотрим foo в контексте с участием Derived, Тем не менее, много много Лучшим решением является использование уникальных идентификаторов для уникальных функций:

struct X; struct Base                  { virtual void foox(X *); };
struct Y; struct Derived : public Base { virtual void fooy(Y *); };

void f(Derived *d, X *x) { d->foox(x); }

Здесь нет путаницы в том, какую функцию вы хотели вызвать — нет путаницы со стороны компилятора, а также нет путаницы со стороны человеческого читателя. Перегрузка функций в C ++ — это инструмент, предназначенный для решения очень специфической проблемы. Если у вас нет этой проблемы, не используйте этот инструмент!

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]