I am learning c++ and writing a game. it was going more or less okey. but the bigger it gets the more trouble i get from dependencies.
How can i fix this kind of dependency?
class myClass_2;
class myClass_1 {
private:
myClass_2 * myclass2;
public:
myClass_1() {}
void setUp(myClass_2 &myclass) {
myclass2 = &myclass;
}
void doSomething_1(){
myclass2->doSomething_2();
}
};
class myClass_2 {
private:
myClass_1 * myclass1;
public:
myClass_2() {}
void setUp(myClass_1 &myclass) {
myclass1 = &myclass;
}
void doSomething_2() {
myclass1->doSomething_1();
}
};
int main () {
myClass_1 class_1;
myClass_2 class_2;
class_1.setUp(class_2);
class_2.setUp(class_1);
return 1;
}
You need to separate the class definition in a header file (with .h extension) and a source file (.cpp or .cc file). And then use #include to include the header file to solve these types of problems. See this link for a more detailed explanation: Header files in C++
You need to define your classes in header files, and define member functions in cpp files.
//class1.h
class myClass_2;
class myClass_1 {
private:
myClass_2 * myclass2;
public:
myClass_1();
void setUp(myClass_2 &myclass);
void doSomething_1();
};
//class1.cpp
#include "class1.h"
#include "class2.h"
myClass_1::myClass_1() {
}
void myClass_1::setUp(myClass_2 &myclass) {
myclass2 = &myclass;
}
void myClass_1::doSomething_1() {
myclass2->doSomething_2();
}
Then do the same for myClass_2. You don't need myClass_2's member function definition in order to call the member functions, you only need the class definition found in class2.h
Move the function bodies outside the class bodies.
class myClass_2;
class myClass_1 {
private:
myClass_2 * myclass2;
public:
myClass_1() {}
void setUp(myClass_2 &myclass);
void doSomething_1();
};
class myClass_2 {
private:
myClass_1 * myclass1;
public:
myClass_2() {}
void setUp(myClass_1 &myclass);
void doSomething_2();
};
void myClass_1::setUp(myClass_2 &myclass) {
myclass2 = &myclass;
}
void myClass_1::doSomething_1(){
myclass2->doSomething_2();
}
void myClass_2::setUp(myClass_1 &myclass) {
myclass1 = &myclass;
}
void myClass_2::doSomething_2() {
myclass1->doSomething_1();
}
int main () {
myClass_1 class_1;
myClass_2 class_2;
class_1.setUp(class_2);
class_2.setUp(class_1);
return 1;
}
In professional object-oriented programming class function declarations and definitions are often kept in separate *.h and *.cpp files. Then the *.h file is included in the main file.
I wish you had said what trouble you were getting exactly.
If the trouble is that it can't compile myClass_1::doSomething1() because it doesn't know how to call myclass2->doSomething2(), the solution is to move the definition of myClass_1::doSomething1() below the definition of myclass_2:
class MyClass_1 {
...
void doSomething_1(); // just declare it here
...
}
class My_Class_2 {
...
void doSomething_2();
...
}
void MyClass_1::doSomething_1() // now define it
{
myclass2->doSomething_2();
}
Related
I am no doubt overlooking something basic but my implementation is obviously flawed.
I am trying to require a derived classes to implement a method being called in a base class.
class IClock
{
public:
virtual void OnTimeExpired() = 0;
}
class Clock : public IClock
{
... // ABC not implemented
}
class Application : public Clock
{
... // ABC not implemented
}
class DerivedApp : public Application
{
public:
virtual void OnTimeExpired() { ... }
}
I rarely use pure ABCs, so I thought by not defining the pure virtual method in Clock and Application, it would require all derivatives of Application to define the OnTimeExpired() method.
I discovered this will compile and link (MSVS-2017) and if DerivedApp does not implement the method, the Clock object will call an undefined method and crash.
Why does this compile without the pure virtual method being implemented?
How do I force derived Application classes to implement the OnTimeExpired() method?
EDIT: The crash was due to unrelated error - I apologize. Nevertheless the questions I ask are still applicable.
As requested here is a complete, buildable, minimal example:
IClock.h:
#pragma once
class IClock
{
public:
virtual void OnClockTime() = 0;
};
Clock.h:
#pragma once
#include "IClock.h"
class Clock : public IClock
{
public:
Clock();
virtual ~Clock();
void ClockUpdate();
virtual void OnClockTime();
private:
float elapsed_time;
};
Clock.cpp:
#include "Clock.h"
Clock::Clock()
: elapsed_time(0.0f)
{
}
Clock::~Clock()
{
}
void Clock::ClockUpdate()
{
elapsed_time += 0.0000001f; // small ticks for testing
if (elapsed_time >= 1.0f) {
OnClockTime();
elapsed_time -= 1.0f;
}
}
void Clock::OnClockTime()
{}
ApplicationBase.h
#pragma once
#include "Clock.h"
class ApplicationBase : public Clock
{
public:
ApplicationBase();
virtual ~ApplicationBase();
virtual void Init(){}
virtual void Run(){}
protected:
bool app_run;
};
ApplicationBase.cpp:
#include "ApplicationBase.h"
ApplicationBase::ApplicationBase()
: app_run(false)
{
}
ApplicationBase::~ApplicationBase()
{
}
DerivedApp.h:
#pragma once
#include "ApplicationBase.h"
class DerivedApp : public ApplicationBase
{
public:
DerivedApp();
virtual ~DerivedApp();
virtual void Init() {}
virtual void Run();
//virtual void OnClockTime();
};
DerivedApp.cpp:
#include "DerivedApp.h"
#include <iostream>
DerivedApp::DerivedApp()
{
}
DerivedApp::~DerivedApp()
{
}
void DerivedApp::Run()
{
app_run = true;
while (app_run) {
ClockUpdate();
}
}
//void DerivedApp::OnClockTime()
//{
// static int counts(0);
// std::cout << "Tick..." << std::endl;
// counts++;
// if (counts >= 10)
// app_run = false;
//}
main.cpp
#include "DerivedApp.h"
class App : public DerivedApp
{
public:
App(){}
~App(){}
};
int wmain(int argc, wchar_t * argv[])
{
App *app = new App();
app->Init();
app->Run();
delete app;
}
Thanks to those who requested a minimal working example, I built it and it works exactly as I had hoped. The complier will complain about no instantiation of the ABC in the App class. If I remove the comments from DerivedApp::OnClockTime() it compiles and runs the way I wish. Obviously my actual code is not following this model as I thought, so now I need to reexamine where I went wrong. Thanks.
There is no keyword in C++ that forces a class to override some method. However, by making OnTimeExpired() pure virtual you're making IClock an abstract class. Any classes deriving from IClock that do not implement OnTimeExpired() will automatically become an abstract class too, thus not allowing you to create objects of these classes. This means that your code as-is is completely legal unless you try to make objects of these classes
class AbstractBase {
public:
virtual void someFunc() = 0; // Purely Virtual
};
class AbstractDerived : public AbstractBase {
public:
void someOtherFunc();
// Still abstract because the following is not declared-defined
// void someFunc() override { ... }
};
class NonAbstractDerivedA : public AbstractBase { // Derived From Base
public:
void someFunc() override { /* do this class's implementation*/ }
};
class NonAbstractDerivedB : public AbstractDerived { // Derived From AbstractDerived
public:
void someFunc() override { /* do this class's implementation*/ }
};
uses:
#include "above"
int main() {
AbstractBase base; // compiler error
AbstractDerived derived; // compiler error
NonAbstractDerivedA derivedA; // should be okay
NonAbstractDerivedB derivedB; // should be okay
return 0;
}
In Objective C the language has built in support for delegation of classes to other classes. C++ does not have such feature (one class as a delegate of another class) as part of the language. A way to mimic that is to separate declaration and implementation this way:
In header file a.h:
class AImpl;
class A
{
public:
A();
void f1();
int f2(int a, int b);
// A's other methods...
private:
AImpl *mImpl;
};
In the .cpp (implementation file):
#include "a.h"
class AImpl
{
public:
AImpl();
// repeating the same method declarations from A
void f1();
int f2(int a, int b);
// AImpl's other methods
};
AImpl::AImpl()
{
}
void AImpl:f1()
{
// actual implemetation
}
int AImpl::f2(int a, int b)
{
// actual implmentation
}
// AImpl's other methods implementation
A::A()
{
mImpl = new AImpl();
}
// A's "forwarder"
void A::f1()
{
mImpl->f1();
}
int A::f2(int a, int b)
{
return mImpl->f2(a, b);
}
// etc.
This requires manually creating all "forwarder" functions in the class that would delegate to another class to do the actual work. Tedious, to say the least.
The question is: is there a better or more productive way to achieve this effect using templates or other C++ langage constructs?
Yes it's possible. One of possible examples is:
struct WidgetDelegate
{
virtual ~WidgetDelegate() {}
virtual void onNameChange(std::string newname, std::string oldname) {}
};
class Widget
{
public:
std::shared_ptr<WidgetDelegate> delegate;
explicit Widget(std::string name) : m_name(name){}
void setName(std::string name) {
if (delegate) delegate->onNameChange(name, m_name);
m_name = name;
}
private:
std::string m_name;
};
Usage:
class MyWidgetDelegate : public WidgetDelegate
{
public:
virtual void onNameChange(std::string newname, std::string oldname) {
std::cout << "Widget old name: " << oldname << " and new name: " << newname << std::endl;
}
};
int main()
{
Widget my_widget("Button");
my_widget.delegate = std::make_shared<MyWidgetDelegate>();
my_widget.setName("DoSomeThing");
return 0;
}
Required includes are:
#include <string>
#include <iostream>
#include <memory>
You can implement a virtual interface in the base class.
However, if you really want to delegate, then you can overload the operator-> to delegate all calls.
You won't need anymore the forwarding methods:
#include <iostream>
#include <string>
using namespace std;
class AImpl;
class A
{
public:
A();
//Overloading operator -> delegates the calls to AImpl class
AImpl* operator->() const { return mImpl; }
private:
AImpl *mImpl;
};
class AImpl
{
public:
void f1() { std::cout << "Called f1()\n"; }
void f2() { std::cout << "Called f2()\n"; }
};
A::A()
{
mImpl = new AImpl();
}
int main()
{
A a;
a->f1(); //use a as if its a pointer, and call functions of A
A* a1 = new A();
(*a1)->f2();
}
I'm writing a cross-platform class hierarchy, and want to keep the platform dependent implementations in their own class (as opposed to having one class with #ifdefs). This is what I have so far, but the compiler is complaining that BaseDef is private. Any help with how I could keep this basic structure while getting it to compile would be greatly appreciated :-)
Edit: It would seem from here that this isn't possible. Any other way I could keep this general structure and still compile?
Root.h
class Root {
private:
class BaseDef {
virtual void foo() = 0;
virtual void bar() = 0;
};
#ifdef _WIN32
class WinImp;
#else
class NixImp;
#endif
BaseDef* imp;
BaseDef* getImp();
public:
Root() : imp(getImp()) {}
void foo();
void bar();
};
Root.cpp
#include "Root.h"
void Root::foo() {
imp->foo();
}
void Root::bar() {
imp->bar();
}
WinImp.h
#ifdef _WIN32
#include "Root.h"
class WinImp : public Root::BaseDef {
public:
void foo();
void bar();
};
#endif
WinImp.cpp
#include "WinImp.h"
#ifdef _WIN32
Root::WinImp::foo() {
}
Root::WinImp::bar() {
}
Root::BaseDef* Root::getImp() {
return new Root::WinImp();
}
#endif
Your main problem is that BaseDef is private. That means that other classes (aside from Root itself) cannot access the BaseDef name. One way is to make BaseDef public. Alternatively you can make the derived classes (WinImp and NixImp) friends of Root so that they can access the BaseDef name. In addition Root cannot access the members of BaseDef so they need to be public or make Root a friend of BaseDef.
class Root {
private:
class BaseDef {
public:
// These need to be public so that Root can see them or Root needs to be a friend.
//Nothing else can see BaseDef though so this is safe.
virtual void foo() = 0;
virtual void bar() = 0;
};
class WinImp; // Forward declare the classes
friend class WinImp; // And then make them friends
class NixImp;
friend class NixImp;
BaseDef* imp;
BaseDef* getImp();
public:
Root() : imp(getImp()) {}
void foo();
void bar();
};
void Root::foo() {
imp->foo();
}
void Root::bar() {
imp->bar();
}
// Since this is a nested class i made it Root::WinImp
class Root::WinImp : public Root::BaseDef {
public:
void foo();
void bar();
};
void Root::WinImp::foo() {}
void Root::WinImp::bar() {}
Root::BaseDef* Root::getImp() {
return new WinImp();
}
This method is not allowed according to the 2003 standard (11.4.p2) but in C++11 (same example) it is explicitly allowed (11.3.p2). However, clang (3.1 tested) accepts this even in 2003 mode. gcc (4.7.2 tested) accepts this (even in 2003 mode) so long as the derived classes are nested inside the same class but not if outside the class.
It's complaining that BaseDef is private...
class Root {
private:
class BaseDef {
virtual void foo() = 0;
virtual void bar() = 0;
};
So make it public...
class Root {
public:
class BaseDef {
virtual void foo() = 0;
virtual void bar() = 0;
};
Footnote:
You're trying to avoid #ifdef, so get rid of this:
#ifdef _WIN32
class WinImp;
#else
class NixImp;
#endif
Instead, just use a single class:
class Imp;
Need help with implementing a pure abstract class via inheritance, using namespace to wrap all my classes to avoid conflict with others.
I have been able to build and run the code successfully if I remove namespace wrapper from my abstract class and all classes that inherit from my pure abstract class.
It seems like Visual Studio 2010 compiler is complaining that despite all classes are in the same namespace, the abstract class's pure abstract method is not implemented.
Any help would be much appreciated.
//IBaseClass.h
//forward declaration
class ConcreteClass;
//namespace MyCustomNamespace
//{
class IBaseClass
{
public:
virtual ~IBaseClass() { /*virtual destructor*/ }
//Behaviours...
virtual bool Method001( const ConcreteClass &cc ) = 0;
//virtual bool Method002(/*some input*/) = 0;
};
//} /*NAMESPACE*/
//-----------------------------------------
//ParentClass.h
//namespace MyCustomNamespace
//{
class ParentClass : virtual public IBaseClass
{
private:
int a;
public:
virtual ~ParentClass() { /*virtual destructor*/ }
//getter-setter implemented in ParentClass.cpp file...
void setA(const int aa);
const int getA() const;
};
//} /*NAMESPACE*/
//-----------------------------------------
//ConcreteClass.h
//namespace MyCustomNamespace
//{
class ConcreteClass: public ParentClass
{
private:
int b;
public:
virtual ~ConcreteClass() { /*virtual destructor*/ }
//getter-setter...
void setB(const int bb);
const int getB() const;
bool Method001( const ConcreteClass &cc ); //re-declaring IBase abstract method...
};
//} /*NAMESPACE*/
//-----------------------------------------
//ConcreteClass.cpp
//namespace MyCustomNamespace
//{
void ConcreteClass::setB(const int bb) { this->b = bb; }
const int ConcreteClass::getB() const { return this->b; }
bool ConcreteClass::Method001( const ConcreteClass &cc )
{
//implementation code goes here...
return false;
}
//} /*NAMESPACE*/
The problem is that your forward class has been declared in another namespace (specifically, the global namespace). Thus, the virtual to override is a different symbol with a different parameter type.
As written, the compiler matches ConcreteClass to the forward declaration it sees in the global namespace when declared in the base:
virtual bool Method001( const ConcreteClass &cc ) = 0;
When you declare Method001 in ConcreteClass:
virtual bool Method001( const ConcreteClass &cc );
the compiler matches cc to MyCustomNamespace::ConcreteClass because that is a more accurate match.
To resolve the issue, just place your forward declaration in the proper namespace:
namespace MyCustomNamespace {
class ConcreteClass;
}
I have a problem creating some form of hierarchy with different object types. I have a class which has a member of another class, like this:
class A
{
public:
A(){}
~A(){}
void addB(B* dep){
child = dep;
dep->addOwner(this);
}
void updateChild(){
child->printOwner();
}
void print(){
printf("Printing...");
}
private:
B* child;
};
And this is class B:
class B
{
public:
void addOwner(A* owner){
ownerObject = owner;
}
//ISNT WORKING
void printOwner(){
ownerObject->print();
}
private:
A* ownerObject;
};
Calling a function of "B" out of class "A" works just fine but trying it vice versa gives a compiler error because A is not defined in B. It actually is by using an include and a forward declaration, but I guess its a cross reference problem which the compiler can not solve.
Is there any chance to solve this problem or should I rethink my design?
You say that you already solved your circular dependency problem by using a forward declaration of A instead of including the header where A is defined, so you already know how to avoid circular includes. However, you should be aware of what is possible and what is not with incomplete types (i.e. types that have been forward declared).
In your case, you try to call the member function print on an object that has an incomplete type; the compiler knows nothing about this type excepts that it will be defined at some point, so it does not allow you to do this. The solution is to remove the implementation of the printOwner member function from the B header and put it into an implementation file:
//B.hpp
class A; // forward declaration
class B
{
public:
void addOwner(A* owner);
void printOwner() const; // I think this member function could be const
private:
A* ownerObject;
};
//B.cpp
#include "B.hpp"
#include "A.hpp" // here we "import" the definition of A
void B::addOwner(A * owner)
{
ownerObject = owner;
}
void B::printOwner() const
{
ownerObject->print(); //A is complete now, so we can use its member functions
}
You could possibly do the same thing in the A header.
You can use forward declaration, and define the member functions outside of the class, i.e.
// A.h
class B;
class A { public:
void addB(B* dep); // don't define addB here.
...
};
// B.h
class A;
class B { public:
void addOwner(A* owner); // don't define addOwner here.
...
};
// A.cpp
#include "A.h"
#include "B.h"
void A::addB(B* dep) {
...
}
// B.cpp
// similar.
You probably should rethink your design, since a crcular parent-child relationship is usually a code smell.
But, you can make the compiler happy :
#include <cstdlib>
#include <cstdio>
class A
{
public:
A(){}
~A(){}
void addB(class B* dep);
void updateChild();
void print(){
printf("Printing...");
}
private:
class B* child;
};
class B
{
public:
void addOwner(A* owner){
ownerObject = owner;
}
//ISNT WORKING
void printOwner(){
ownerObject->print();
}
private:
A* ownerObject;
};
void A::addB(class B* dep){
child = dep;
dep->addOwner(this);
}
void A::updateChild(){
child->printOwner();
}
int main()
{
return 0;
}
You should move B::printOwner implementation to .cpp file.