그래서, 당신은 같은 것을 가지고
class CSound {
// Whatever
};
class CSoundEngine {
// A lot of stuff
CSound* createSound(/* ... */);
};
을 그리고 당신은 CSound에 반환 할 싶지는 않지만 인터페이스는, 그것이 내부적와 벡터에 저장되어 있지만 특정 유형의 ?
당신의 인터페이스를 만들고 그들로부터 파생 : - 인터페이스 - 그럼 첫 번째 문제
는 해결하기 쉽습니다. 당신이 괜찮 ISound에서 파생 만 CSound에 사용하려는 경우
class ISound {
public:
ISound(const ISound&) = delete;
ISound(ISound&&) = delete;
ISound& operator =(const ISound&) = delete;
ISound& operator =(ISound&&) = delete;
virtual ~ISound() = default;
// Your ISound public API here as pure virtual methods, e.g.:
virtual const std::string name() const = 0;
protected:
ISound() = default;
};
class ILoopable {
public:
ILoopable(const ILoopable&) = delete;
ILoopable(ILoopable&&) = delete;
ILoopable& operator =(const ILoopable&) = delete;
ILoopable& operator =(ILoopable&&) = delete;
virtual ~ILoopable() = default;
// Your ILoopable public API here as pure virtual methods, e.g.:
virtual const bool isLoopingActive() const = 0;
virtual bool setLoopingActive(bool) = 0;
protected:
ILoopable() = default;
};
class CDefaultSound
: public ISound {
public:
CDefaultSound() = default;
// ISound implementation
inline const std::string name() const { return mName; }
private:
std::string mName;
};
class CLoopableSound
: public ISound,
public ILoopable {
public:
CLoopableSound()
: ISound(),
ILoopable(),
mLoopingActive(true),
mName("")
{
}
// ISound implementation
inline const std::string name() const { return (mName + "(Loopable)"); }
// ILoopable implementation
inline const bool isLoopingActive() const { return mLoopingActive; }
inline bool setLoopingActive(bool active) { mLoopingActive = active; }
private:
bool mLoopingActive;
std::string mName;
};
int main()
{
// Now you can do something like this, for example, using polymorphism
// in your CSoundEngine (see below)...
ISound *pDef = new CDefaultSound();
ISound *pLoopable = new CLoopableSound();
}
, 당신은 여러 클래스를 필요로하지 않지만, 그때 인터페이스를 사용하는 점을 이해하지 않습니다. 중요 : 순수 가상 인터페이스 메서드로 인해 인터페이스 클래스를 설치할 수 없으므로 shared_ptr 또는 unique_ptr과 같은 포인터 또는 RAII 포인터를 사용해야합니다 (RAII 권장 사항 ...)
두 번째 문제 - 특정 유형을 벡터에 저장하는 것 - 단일 벡터 foreach 허용 유형이 필요 했으므로 훨씬 더 어렵습니다. 또는! 인터페이스 인스턴스를 저장하고 인터페이스 메소드 만 사용하십시오!
class DefaultSoundCreator {
static ISound* createSound(/* Criteria */) { ... }
};
template <typename TSoundCreator>
class CSoundEngine {
public:
CSoundEngine()
: mSoundCreator() {
}
std::shared_ptr<ISound> createSound(/* some criteria */);
private:
std::vector<std::shared_ptr<ISound>> mSounds;
};
// cpp
std::shared_ptr<ISound> CSoundEngine::createSound(/* some criteria */) {
// Use criteria to create specific sound classes and store them in the mSOunds vector.
ISound *pSound = TSoundCreator::createSound(/* forward criteria for creation */);
std::shared_ptr<ISound> pSoundPtr = std::shared_ptr<ISound>(pSound);
mSounds.push_back(pSoundPtr);
return pSoundPtr;
}
int main() {
std::unique_ptr<CSoundEngine<DefaultSoundCreator>> pEngine = std::make_shared<CSoundEngine<DefaultSoundCreator>>();
std::shared_ptr<ISound> pSound = pEngine->createSound(/* Criteria */);
}
당신이 ISound에서 제공하는 기능에 의존 수있는이 방법하지만 창조주 클래스를 지정하여, 당신은 일반적인 사운드 엔진 사운드 생성을 제어 할 수있다.
이제 인터페이스 기반 클래스를 사용하여 실제로 유형을 지우는 문제 : 인덱스 2에 CLoopableSound를 저장했지만 사운드 엔진의 createSound() 메소드 인 std :: shared_ptr로 인해 ISound-Interfacemethods 만 사용할 수 있다는 사실을 알고있었습니다. ;
ILoopable- 비헤이비어에 어떻게 액세스합니까?
그리고이 그것을 철학적가되는 지점입니다 ... 내가 추천 읽기 :
https://akrzemi1.wordpress.com/2013/11/18/type-erasure-part-i/ Type erasure techniques https://aherrmann.github.io/programming/2014/10/19/type-erasure-with-merged-concepts/
하나 개의 기술 제가 사용하려면 : 마지막으로
class CLoopableSound
: public ISound {
// All the above declarations and definitions
// AND:
static std::shared_ptr<CLoopableSound> fromISound(const std::shared_ptr<ISound>& other, bool *pSuccess = nullptr) {
std::shared_ptr<CLoopableSound> p = std::static_pointer_cast<CLoopableSound>(other);
if(pSuccess)
*pSuccess = p.operator bool();
return p;
}
};
// Use like
std::shared_ptr<CLoopableSound> pLoopable = CLoopableSound::fromISound(pSoundEngine->getSound(...));
if(pLoopable) {
// Use
}
, 물론 FromISound 함수를 템플릿으로 만들고 캐스트를 사용하여 CLoopableSound 대신 ILoopable에만 액세스 할 수 있습니다.
왜 두 가지 다른 언어를 묻는 중입니까? 그것은 당신의 질문을 너무 넓게 만듭니다. 가장 관심이 적은 질문을 삭제하십시오. –
질문의 두 번째 부분을 이해하지 못합니다. 명확히하십시오. –
이 질문은 위험한 것처럼 보입니다 ... 추상적 기본 클래스가 사용되는 것에 대해 묻고 있습니까? 만약 당신이 어떤 코드를 작성하고 당신이 의미심장 한 예에서 무엇을하려고하는지 보여주는 것이 더 좋을 것입니다. – luk32