I have a C++/WinRT base class that I need to subclass. My problem is that I don't manage to call the base class's protected constructor from the subclass.
That base class is defined in MIDL as follows:
namespace My.Custom.WindowsRuntimeComponent
{
unsealed runtimeclass BaseClass : Windows.UI.Xaml.Controls.SwapChainPanel
{
}
}
From it, the following header and implementation is created:
#pragma once
#include <DirectXMath.h>
#include "BaseClass.g.h"
namespace winrt::My::Custom::WindowsRuntimeComponent::implementation
{
struct BaseClass : BaseClassT<BaseClass>
{
protected:
BaseClass();
::DirectX::XMFLOAT3 ProtectedMethod();
};
}
#include "pch.h"
#include "BaseClass.h"
#include "BaseClass.g.cpp"
namespace winrt::My::Custom::WindowsRuntimeComponent::implementation
{
BaseClass::BaseClass()
{
// Important stuff happening here
}
::DirectX::XMFLOAT3 BaseClass::ProtectedMethod()
{
return ::DirectX::XMFLOAT3();
}
}
The subclass's MIDL, header and implementation are defined as follows:
import "BaseClass.idl";
namespace My.Custom.WindowsRuntimeComponent
{
runtimeclass SubClass : BaseClass
{
SubClass();
void UseProtectedMethod();
}
}
#pragma once
#include "BaseClass.h"
#include "SubClass.g.h"
namespace winrt::My::Custom::WindowsRuntimeComponent::implementation
{
struct SubClass : SubClassT<SubClass, My::Custom::WindowsRuntimeComponent::implementation::BaseClass>
{
SubClass();
void UseProtectedMethod();
};
}
namespace winrt::My::Custom::WindowsRuntimeComponent::factory_implementation
{
struct SubClass : SubClassT<SubClass, implementation::SubClass>
{
};
}
#include "pch.h"
#include "SubClass.h"
#include "SubClass.g.cpp"
namespace winrt::My::Custom::WindowsRuntimeComponent::implementation
{
SubClass::SubClass()
{
}
void SubClass::UseProtectedMethod()
{
::DirectX::XMFLOAT3 value = ProtectedMethod();
}
}
The above example compiles. However, if I attempt to call the protected base class constructor from the initializer list of the subclass as shown below I receive a compiler error.
#include "pch.h"
#include "SubClass.h"
#include "SubClass.g.cpp"
namespace winrt::My::Custom::WindowsRuntimeComponent::implementation
{
SubClass::SubClass() : BaseClass() // This line does not compile
{
}
void SubClass::UseProtectedMethod()
{
::DirectX::XMFLOAT3 value = ProtectedMethod();
}
}
The compiler error is as follows:
error C2614: 'winrt::My::Custom::WindowsRuntimeComponent::implementation::SubClass': illegal member initialization: 'BaseClass' is not a base or member
Both in the MIDL and the header of SubClass I specify that it inherits from BaseClass so it is unclear to me why the compiler emits that error.
I could work around that problem, I guess, but I'm curious about what exactly is going on here. Any hints?
The SubClass in the winrt::... namespace derives from SubClassT<...>, not from SubClass.
The SubClass that is outside the winrt:: namespace derives from BaseClass, but thats a different one. Your naming is easy to get lost in.
I got two classes separated in four files. The main class includes a sub class and needs to execute functions of it (not shown in the minimal example code). What I want to do is to execute a function of the main class in the scope of the subclass.
I think some ideas would be to inherit the functions in the sub class but I could not figure out how to do this.
MainClass.cpp
#include "MainClass.hpp"
void MainClass::mainCallback() {
std::cout << "[mainCallback] executed" << std::endl;
}
void MainClass::subCallback() {
std::cout << "[subCallback] executed" << std::endl;
}
int main() {
MainClass mainClass;
mainClass.mainCallback();
SubClass subClass;
subClass.activateSubClass();
return 0;
}
MainClass.hpp
#pragma once
#include "SubClass.hpp"
#include <iostream>
class MainClass{
public:
void mainCallback();
void subCallback();
};
SubClass.cpp
#include "SubClass.hpp"
void SubClass::activateSubClass(){
mainClass.subCallback(); //TODO call this function from this scope
}
SubClass.hpp
#pragma once
class SubClass{
public:
void activateSubClass();
};
The error in SubClass.cpp is of course:
error: use of undeclared identifier 'mainClass'
Just subclass the subclass:
class SubClass: public MainClass {
public:
void activateSubClass();
};
This (public) way the SubClass makes all methods of MainClass callable in SubClass instances. You could also private inherit. That way only activateSubClass() 'ld be callable.
In activateSubClass you can call directly the methods of the parent class:
void SubClass::activateSubClass(){
mainClass.subCallback(); //TODO call this function from this scope
}
Don't forget to include MainClass.hpp in SubClass.hpp
You try to call a MainClass.subCallback() without having an instance of MainClass. According to me, this is the typical use case for static methods.
Then, I think you make your #include directives the wrong way. Indeed, MainClass does not seem to need to know SubClass but the opposite is true. I think it is better to include MainClass.hpp in SubClass.hpp. This will solve your circle dependencies problem.And you can write your main() function in another file.
EDIT: Example
MainClass.hpp:
#pragma once
class MainClass
{
public:
void mainCallback();
static void subCallback(); // mak it static to be able to call it without an instance of the class
};
MainClass.cpp:
#include "MainClass.hpp"
#include <iostream>
void MainClass::mainCallback()
{
std::cout << "[mainCallback] executed" << std::endl;
}
void MainClass::subCallback()
{
std::cout << "[subCallback] executed" << std::endl;
}
SubClass.hpp:
#pragma once
class SubClass
{
public:
void activateSubClass();
};
SubClass.cpp:
#include "SubClass.hpp"
#include "MainClass.hpp" // MainClass inclusion
void Suclass::activateSubClass()
{
MainClass::subCallback(); // Call of the static method
}
main.cpp:
#include "MainClass.hpp"
#include "SubClass.hpp"
int main()
{
MainClass mc;
mc.mainCallback();
SubClass sc;
sc.activateSubClass(); // Will call MainClass::subCallback()
return 0;
}
I hope it can help you.
This is related to my last post that you can find here: Creating an unordered_map of std::functions with any arguments. I have now gone ahead and extended this out to classes. So let's say I have three different classes. And these classes all have different methods except for getVariable() and setVariable(int). So for this example we will class them ClassA, ClassB, and ClassC.
I also have a base class which I want to use as my driver. Essentially, if I want to set the variable between ClassA and ClassC I would call the base class' setVariable function.
#ifndef BASE_CLASS_HPP
#define BASE_CLASS_HPP
#include <unordered_map>
#include <functional>
#include <utility>
#include <string>
#include <any>
template<class A, class B>
class BaseClass
{
public:
BaseClass() { bindThem(); }
std::pair<int,int> getValue()
{
// return classA and ClassB's values
}
void setValue(int newVal)
{
auto iter = functions.equal_range("setValue");
std::any_cast<void(*)(int)>(mapIter->second)(newVal);
}
private:
std::unordered_multimap<std::string,std::any> functions;
void bindThem()
{
functions.emplace("setValue",&A::setValue);
functions.emplace("setValue",&B::setValue);
functions.emplace("getValue",&A::getValue);
functions.emplace("getValue",&B::getValue);
}
};
I then have in main:
#include <iostream>
#include "baseClass.hpp"
#include "classA.hpp"
#include "classB.hpp"
#include "classC.hpp"
int main()
{
ClassA a;
ClassB b;
ClassC c;
c.setValue(20);
BaseClass<ClassA,ClassB> base1;
BaseClass<ClassA,ClassC> base2;
base1.setValue(15);
auto values = base1.getValues();
}
I can place the functions withing my map, however, when I try to any_cast I don't get anything in return. I also tried:
std::any_cast<void(A::*)(int)>(mapIter->second)(newVal);
But that also gives me a compiler error of must use .* or ->* and I have tried everything to get it to compile and I don't really know what I am doing wrong. I also realized, if I called it that way, then I wouldn't be able to access B's setVariable function since I am using A's namespace.
Is there anyway I can get this to work how I want it to? I am essentially trying to modify those class values without having to make any copies of those classes and instead directly modify them from within this driver.
I still don't quite understand the purpose of such structure, but here an option how to make it at least compile:
#include <unordered_map>
#include <functional>
#include <utility>
#include <string>
#include <any>
template<class A, class B>
class BaseClass
{
public:
BaseClass() { bindThem(); }
std::pair<int,int> getValue()
{
auto range = functions.equal_range("getValue");
return
{
(a.*std::any_cast<int(A::*)()>(*range.first))(),
(b.*std::any_cast<int(B::*)()>(*range.second))()
};
}
void setValue(int newVal)
{
auto range = functions.equal_range("setValue");
(a.*std::any_cast<void(A::*)(int)>(*range.first))(newVal);
(b.*std::any_cast<void(B::*)(int)>(*range.second))(newVal);
}
private:
std::unordered_multimap<std::string,std::any> functions;
void bindThem()
{
functions.emplace("setValue",&A::setValue);
functions.emplace("setValue",&B::setValue);
functions.emplace("getValue",&A::getValue);
functions.emplace("getValue",&B::getValue);
}
A a;
B b;
};
class ClassA
{
public:
void setValue(int){}
int getValue() {return 0;}
};
class ClassB
{
public:
void setValue(int){}
int getValue() {return 1;}
};
int main()
{
BaseClass<ClassA, ClassB> x;
x.setValue(3);
auto i = x.getValue();
}
Please note several things:
I've added members to BaseClass since to call member functions you need an object to be called on.
I'm using first and last iterators of the range from equal_range, but the order of elements in that range is implementation defined. So to make things work you need to take care of distinguishing which container element corresponds to class A and which to class B.
I am getting a C2504 compilation error in PlayerController.h saying that my base class (Updateable) is undefined. I have searched for several hours for a solution to a circular inclusion with inheritance problem and their solutions are to remove the circular inclusions and jsut use a forward declaration. As far as I understand, this works if no methods from the forward declared class are called. However, in my program my Updateables class calls a method on its member inherited gameObject object and the GameObjects also call methods on their member Updateables. Because of this, Updateables need to include GameObject.h and GameObjects need to include Updateables.h. This leads to a C2504 in PlayerController.h saying that the base class Updateable can not be found.
Here are my relevant classes:
Component.h
#pragma once
#include "Vector3.h"
class GameObject;
class Component {
public:
GameObject* gameObject = nullptr;
Component();
};
Component.cpp
#include "Component.h"
Component::Component() {}
Updateable.h
#pragma once
#include "Component.h"
#include "GameObject.h"
class GameObject;
class Updateable : public Component {
public:
~Updateable();
virtual void update() = 0;
};
Updateable.cpp
#include "Updateable.h"
Updateable::~Updateable() {
if (gameObject) {
gameObject->removeUpdateable(this);
}
}
GameObject.h
#pragma once
#include "Updateable.h"
#include "GameManager.h"
class Updateable;
class GameObject {
public:
GameObject();
~GameObject();
void runUpdateables();
void addUpdateable(Updateable* updateable);
void removeUpdateable(Updateable* updateable);
private:
vector<Updateable*> updateables;
};
GameObject.cpp
#include "GameObject.h"
GameObject::GameObject() {
updateables = vector<Updateable*>();
GameManager::addGameObject(this);
}
GameObject::~GameObject() {
GameManager::removeGameObject(this);
}
void GameObject::runUpdateables() {
for (unsigned int i = 0; i < updateables.size(); i++) {
updateables[i]->update();
}
}
void GameObject::addUpdateable(Updateable* updateable) {
updateables.push_back(updateable);
updateable->gameObject = this;
}
void GameObject::removeUpdateable(Updateable* updateable) {
auto it = find(updateables.begin(), updateables.end(), updateable);
if (it != updateables.end()) {
updateables.erase(it);
}
}
PlayerController.h
#pragma once
#include "Updateable.h"
//#include "GameObject.h"
#include "Input.h"
class Updateable;
class PlayerController : public Updateable {
public:
float speed = 5.0f;
void update();
};
PlayerController.cpp
#include "PlayerController.h"
void PlayerController::update() {
float x = 0;
if (Input::getKeyDown(GLFW_KEY_A)) {
x = -speed;
}
if (Input::getKeyDown(GLFW_KEY_D)) {
x = speed;
}
cout << x << endl;
gameObject->getRigidBody()->velocity.x = x;
//yes this is a method in GameObject that I removed from this post
//because it would take up more space, rigidbody.h does not create
//a circular dependency
}
GameManager.h
#pragma once
#include "GameObject.h"
#include "PlayerController.h"
class GameManager {
public:
static void init();
static void addGameObject(GameObject* go);
static void removeGameObject(GameObject* go);
static void onFrame();
private:
static vector<GameObject*> gameObjects;
static GameObject* box;
GameManager.cpp
#include "GameManager.h"
vector<GameObject*> GameManager::gameObjects;
GameObject* GameManager::box;
void GameManager::init() {
gameObjects = vector<GameObject*>();
box = new GameObject();
box->addUpdateable(new PlayerController());
}
void GameManager::addGameObject(GameObject* go) {
gameObjects.push_back(go);
}
void GameManager::removeGameObject(GameObject* go) {
auto it = find(gameObjects.begin(), gameObjects.end(), go);
if (it != gameObjects.end()) {
gameObjects.erase(it);
}
}
void GameManager::onFrame() {
for (unsigned int i = 0; i < gameObjects.size(); i++) {
gameObjects[i]->runUpdateables();
}
}
Here is the exact error message: Error C2504 'Updateable': base class undefined Basic Platformer c:\users\default.sixcore-pc\documents\visual studio 2015\projects\basic platformer\basic platformer\playercontroller.h 9
A lot of your files have both #include "Class.h" and class Class; declarations. You never need both; use one or the other.
A definition of a class X must be visible when:
accessing the members of X
creating an object of type X
defining a class derived from X
using X as a template argument to a template which requires the corresponding template parameter to be a complete type (such as what standard library containers require of their element type). Note that this applies when using X, not X*.
In other cases (such as creating a pointer to X or declaring a function taking of returning X), a non-defining declaration (class X;) is enough.
Using these rules (plus moving function bodies from headers to source files when necessary), you can solve any circular dependency issues.
To directly address your files as presented:
Updateable.h does not need to #include "GameObject.h". It doesn't even need the forward declaration of GameObject.
GameObject.h doesn't need any of the two #includes in it.
GameManager.h doesn't need any #includes. It needs a declaration of class GameObject; though.
Descendant class must know the full definition of the base class. Forward declaration is not enough and useless.
I have been trying to make a game engine for some time, and for the most part it has been turning out quite well, considering it's the first one i've made. But when I started to make an event send/recieve system with derived classes contained in a base class pointer vector array, I had some trouble making the reciever get the class type and use the proper function; here's what I have:
This is my base class Object:
object.h:
#include "all.h" //Contains '#include "SDL/SDL.h"' and constant variables.
#include <vector>
#include "mask.h" //An unimportant class used for collision checking
class Body;
class Room;
class Object//Objects that belong here are those without step events.
{
public:
vector<vector<Room> > *world_map;//Should hold the address of the world map.
Room *room;//The room holding this object.
unsigned int x;
unsigned int y;
unsigned int pos;//Position of the object in the room's list.
int depth;//The deeper it is, the later it will be drawn.
virtual void draw(SDL_Surface *buffer,int viewx, int viewy){}
virtual void interact(Body *body);//Sends a pointer of this object to the
//the obj_event function of the body calling it.
Object(unsigned int xx=0, unsigned int yy=0,int d=0):x(xx),y(yy),depth(d){}
};
#endif // INSTANCE_H_INCLUDED
object.cpp:
#include "object.h"
#include "body.h"
void Object::interact(Body *body)
{
body->obj_event(this);
}
This is my derived class Body:
body.h:
#ifndef BODY_H_INCLUDED
#define BODY_H_INCLUDED
#include "all.h"
#include "object.h"
class Entity;
class Enemy;
class Player;
class Body : public Object//Objects that belong here are those with step events.
{
public:
int priority;//Decides which body will perform their step event first.
virtual void step()=0;
Body(int xx=0, int yy=0, int d=0, int p=0):Object(xx,yy,d),priority(p){}
//These scripts are for handling objects and bodies it has called through
//interact()
virtual void obj_event(Object *object){}
virtual void obj_event(Entity *entity){}
virtual void obj_event(Enemy *enemy){}
virtual void obj_event(Player *player){}
};
#endif // BODY_H_INCLUDED
there is no body.cpp
This is my derived class of Body, Entity:
entity.h:
#ifndef ENTITY_H_INCLUDED
#define ENTITY_H_INCLUDED
#include "all.h"
#include "body.h"
#include "items.h"
#include <vector>
#include "mask.h"
class Entity : public Body
{
public:
vector<Item> inv;
unsigned int width;
unsigned int height;
Mask mask;
Entity(int xx,int yy,int w,int h,int d=0,int p=0);
void step();
void collide_action(Entity *entity);
virtual void obj_event(Player *player);
virtual void obj_event(Enemy *enemy);
};
#endif // ENTITY_H_INCLUDED
entity.cpp:
#include "entity.h"
#include "room.h"
#include "player.h"
#include "enemy.h"
Entity::Entity(int xx,int yy,int w,int h,int d,int p):Body(xx,yy,d,p),width(w),height(h),mask(xx,yy,w,h,m_rectangle)
{}
void Entity::step()
{
for(int iii=0;iii<room->inv.size();iii++)//Iterates through objects
{
room->inv[iii]->interact(this);
mask.update(x,y,width,height);
}
for(int iii=0;iii<room->index.size();iii++)//Iterates through bodies
{
room->index[iii]->interact(this);
mask.update(x,y,width,height);
}
}
void Entity::collide_action(Entity *entity)
{
if(entity!=this)
{
if (mask_collide(mask,entity->mask))
{
short xchange;
short ychange;
if (entity->x<x)
{
xchange=width-(x-entity->x);
}
else
{
xchange=(entity->x-x)-width;
}
if (entity->y<y)
{
ychange=height-(y-entity->y);
}
else
{
ychange=(entity->y-y)-height;
}
if(abs(xchange)<abs(ychange))
x+=xchange;
else
y+=ychange;
}
}
}
void Entity::obj_event(Player *player)
{
collide_action(player);
}
void Entity::obj_event(Enemy *enemy)
{
collide_action(enemy);
}
This is my derived class of Entity, Player:
player.h:
#ifndef PLAYER_H_INCLUDED
#define PLAYER_H_INCLUDED
#include "all.h"
#include "body.h"
#include "items.h"
#include <vector>
#include "mask.h"
#include "entity.h"
enum keylist
{
kl_left=0,
kl_up=1,
kl_right=2,
kl_down=3,
};
class Player : public Entity
{
public:
SDLKey keys[4]; //List of action's corresponding keys.
Player(int xx,int yy,int w,int h,int d=0,int p=0);
void step();
void draw(SDL_Surface *buffer,int viewx,int viewy);
void interact(Body *body);
};
#endif // PLAYER_H_INCLUDED
player.cpp:
#include "player.h"
#include "room.h"
Player::Player(int xx,int yy,int ww,int hh,int dd,int pp):Entity(xx,yy,ww,hh,dd,pp)
{
//Default keys, can be changed.
keys[kl_left]=SDLK_LEFT;
keys[kl_up]=SDLK_UP;
keys[kl_right]=SDLK_RIGHT;
keys[kl_down]=SDLK_DOWN;
}
void Player::step()
{
Uint8 *key=SDL_GetKeyState(NULL);
if (key[keys[kl_left]])
x-=1;
if (key[keys[kl_right]])
x+=1;
if (key[keys[kl_up]])
y-=1;
if (key[keys[kl_down]])
y+=1;
mask.update(x,y,width,height);
Entity::step();
}
void Player::draw(SDL_Surface *buffer,int viewx,int viewy)
{
FillRect(buffer,x-viewx,y-viewy,width,height,0xFF0000);
}
void Player::interact(Body *body){body->obj_event(this);}
I have another class Enemy, but it's pretty much exactly like player (without the keyboard controls).
Now here's my problem (not error), for every object I want any body to perform an event for, I need to make virtual functions of ALL of them in this base class, that way if any object calls body->obj_event(this), it will pick the proper function with the most derived argument.
For example, if Player called object->interact(this) of an enemy, the enemy would first use it's base class Object's virtual function interact(Body*), which would then check the derived classes if they have an identical function (which enemy does), and then enemy calls body->obj_event(this) of the player body through it's base class, Body. The player body would then first use it's base class Body's virtual function obj_event(Enemy*), which would then check the derived classes if they have an identical function (which Entity does), and then Entity executes obj_event(Enemy*). At least that's how I understand it.
What I'd like to have is a way for any derived class to call interact of any other derived class through it's base function, and would then have it call it's obj_event function for the derived class, without having to have any of the Base classes know about their derived classes.
As I mentioned, this is my first time making an engine, and I'm probably using methods that are completely hectic and error-prone. I was thinking that templates might be able to help out in this situation, but don't know how to implement them.