1. 다이아몬드 상속을 받는 경우, 문제를 야기할 수 있지만, 명시적으로 캐스팅을 함으로써 문제를 해결한다.

//Library.h
#pragma once

struct IObject
{
	virtual void __stdcall Addref() = 0;
	virtual void __stdcall Release() = 0;
	virtual void* __stdcall As(const char* type) = 0;
};

struct IHen : IObject
{
	virtual void __stdcall Cluck() = 0;
	virtual void __stdcall Roost() = 0;
};

struct IHen2 : IHen
{
	virtual void __stdcall Forage() = 0;
};

struct IOfflineChicken : IObject
{
	virtual void __stdcall Load(const char* file) = 0;
	virtual void __stdcall Save(const char* file) = 0;
};

IHen* __stdcall CreateHen();
//Library.cpp
#include "Library.h"
#include <Windows.h>

#define TRACE OutputDebugStringA

struct Hen : IHen2, IOfflineChicken
{
	unsigned m_count;

	Hen() : m_count(0)
	{
		TRACE("Constructor\n");
	}

	~Hen()
	{
		TRACE("Destructor\n");
	}

	// IObject

	void __stdcall Addref()
	{
		++m_count;
	}

	void __stdcall Release()
	{
		if (0 == --m_count)
		{
			delete this;
		}
	}

	void* __stdcall As(const char* type)
	{
		if (0 == strcmp(type, "IHen2") ||
			0 == strcmp(type, "IHen") ||
			0 == strcmp(type, "IObject"))
		{
			Addref();
			return static_cast<IHen2*>(this);
		}
		else if (0 == strcmp(type, "IOfflineChicken"))
		{
			Addref();
			return static_cast<IOfflineChicken*>(this);
		}
		else
		{
			return 0;
		}

	}

	// IHen

	void __stdcall Cluck()
	{
		TRACE("Cluck\n");
	}

	void __stdcall Roost()
	{
		TRACE("Roost\n");
	}

	// IHen2

	void __stdcall Forage()
	{
		TRACE("Forage\n");
	}

	// IOfflineChicken

	void __stdcall Load(const char* /*file*/)
	{

	}

	void __stdcall Save(const char* /*file*/)
	{

	}

};

IHen* __stdcall CreateHen()
{
	IHen* result = new Hen;
	result->Addref();
	return result;
}

2. 레퍼런스 카운터도 잘 동작하지만, hen과 hen2는 같은 주소 값인 반면, As 메소드 덕에, offline은 hen과는 다른 주소 값을 갖는다.

#include "Library.h"

int main()
{
	IHen* hen = CreateHen();

	hen->Cluck();
	hen->Roost();

	IHen2* hen2 = static_cast<IHen2*>(hen->As("IHen2"));

	if (hen2)
	{
		hen2->Forage();
		hen2->Release();
	}

	IOfflineChicken* offline =
		static_cast<IOfflineChicken*>(hen->As("IOfflineChicken"));

	if (offline)
	{
		offline->Save("filename");
		offline->Release();
	}

	hen->Release();
}

 

'삽질 > COM' 카테고리의 다른 글

COM study note 8 IUnknown 이식  (0) 2020.10.30
COM study note 7  (0) 2020.10.29
COM study note 5 레퍼런스 카운터  (0) 2020.10.28
COM study note 4 인터페이스  (0) 2020.10.27
COM study note 3 다이나믹 링킹  (0) 2020.10.27
복사했습니다!