More questions about inheritance

Started by
4 comments, last by MarcusAseth 6 years, 9 months ago

This is a continuation of my previous topic, I am still super confused :P

Situation: There is this "D3DApp" class that is basically a framework to inherit from that give us a Window, a Renderer and a GameTimer. My class "Direct3D11Engine" derives from "D3DApp".

This is how the autor of "3d Game Programming using DirectX11" suggest to initialize my Direct3D11Engine class:


bool Direct3D11Engine::Init()
{
	if (!D3DApp::Init())
	{
		return false;
	}

	//Additional Initialization


	return true;
}

 

Now, from what I can tell something weird is happening, because the D3DApp::Init() method is called from inside my "Direct3D11Engine" fully constructed object.

At a first glance I would assume that a D3DApp object instance was default constructed and it's Init() method called, but that is not the case at all because if it was that way, then that instance would have his own ImmediateContext and swapChain and so on and my derived class would just have a bunch of nullptr instead, but I've tried to draw from within my "Direct3D11Engine" Draw() function and everything works, so that call to D3DApp::Init()  indeed  got my class variable all setup.

What on earth is going on here?! :S

Advertisement

It's hard to say without the code. But probably what you are seeing here is that D3DApp::Init() is being used to call the base class version of Init(). I'd venture to guess that the author is suggesting you use this pattern to allow you to insert any of your application-specific code before or after the base application initialization runs.

There are alternative, better (in my experience) ways of implementing this pattern. But in this case the author is probably opting for simplicity and straightforwardness at the cost of robustness and expecting you to just "remember" to call the base class Init function at the right time.

The Foo::Bar() syntax means different things in different contexts. In this context, it means "explicitly call Foo's version of Bar on the object pointed to by the this pointer."

Ok, probably is what is going on, so this means that from inside a derived class I can call a method of the parent class and the method will act on the derived class variables etc...? Is it really this sneaky?! :D

Example:


class A
{
public:
	A(){}
	virtual ~A();
	virtual void FancyFunction() {value = 20;}
protected:
	int value{};
};

class B : public A
{
public:
	B():A(){}
  	//this function below will set B's member variable "value" to 20
	virtual void FancyFunction() {A::FancyFunction();}
};

 

16 minutes ago, MarcusAseth said:

so this means that from inside a derived class I can call a method of the parent class

Yes, this part is true.

16 minutes ago, MarcusAseth said:

and the method will act on the derived class variables

No, this part is not. The parent (base) class cannot see into the derived class. It doesn't know anything about it, and cannot act on any member variables of the derived class directly.

The Base::Method() syntax you're seeing here is nothing magical, it's just a way of disambiguating, for the compiler, which function you want to call in a case where there are two versions (the base virtual method and the derived overridden method, for example). It is otherwise akin to any regular old member function call.

Your terminology is a little off again, here. In your example, "value" is a member of A. Not B; B doesn't have a member named value of its own, it just has A's value because B inherits from A, and thus every instance of B is also an A. 

When you say things like that something "will act on the derived class variables," what you are saying is that if (continuing your example) B had a member variable called "name," that calling A::FancyFunction from B::FancyFunction could let A set name = "Frank." But that is not possible.

I see. It's pretty awesome, before I had basically copy-pasted all the WinProc function, while now I can just do this (code below) and override only the WM_Message cases I care about, pretty convenient! :P

Learned one more very useful thing, thanks! :)


LRESULT Direct3D11Engine::MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	

	default:
	return  D3DApp::MsgProc(hwnd, msg, wParam, lParam);
	}
}

 

This topic is closed to new replies.

Advertisement