I am developing a client-database using MFC and lately I was trying to create a class in order to perform DAO operations (instead of implementing these operations directly at the CDocument class). I named this class as CModel, and CDocument contains it. In order to perform SQL operations using the CModel class, I must have access to the m_session variable - which represents a database access session - and it can be found in the RecordSet class - which represent one table in a database of mine. Here is a piece of code to better illustrate the situation:
#pragma once
#include "MFCApplicationSet.h"
class CModel
{
public:
CModel(CMFCApplicationSet ApplicationSet);
~CModel();
CMFCApplicationSet * pModelSet;
}
// Model.cpp : implementation file
//
#include "stdafx.h"
#include "MFCApplication.h"
#include "Model.h"
#include "SQLQuery.h"
#include "MFCApplicationSet.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CModel::CModel(CMFCApplicationSet ApplicationSet)
{
pModelSet = &ApplicationSet //not sure if it is right
}
CModel::~CModel()
{
}
// MFCApplicationDoc.h : interface of the CMFCApplicationDoc class
#pragma once
#include "MFCApplicationSet.h"
#include "Model.h"
class CMFCApplicationDoc : public CDocument
{
protected: // create from serialization only
CMFCApplicationDoc();
DECLARE_DYNCREATE(CMFCApplicationDoc)
// Attributes
public:
CMFCApplicationSet m_MFCApplicationSet;
CModel Model;
}
// MFCApplicationDoc.cpp : implementation of the CMFCApplicationDoc class
//
#include "stdafx.h"
#ifndef SHARED_HANDLERS
#include "MFCApplication.h"
#endif
#include "MFCApplicationSet.h"
#include "MFCApplicationDoc.h"
#include "Model.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
IMPLEMENT_DYNCREATE(CMFCApplicationDoc, CDocument)
BEGIN_MESSAGE_MAP(CMFCApplicationDoc, CDocument)
END_MESSAGE_MAP()
// CMFCApplicationDoc construction/destruction
CMFCApplicationDoc::CMFCApplicationDoc()
{
//problem in implementing a instruction to call the Model object constructor
}
CMFCApplicationDoc::~CMFCApplicationDoc()
{
}
I've used the debugger to analyse my code flow and I noticed that, from the CMFCApplicationDoc constructor (CDocument), the constructor from each variable declared in the CMFCApplicationDoc.h is initialized. Here's my problem: I've tried to create a CModel constructor in order to the pModelSet pointer automatically reference the variable m_MFCApplicationSet (check the constructor arguments) declared in the Doc class, but I am experiencing some trouble in giving this instruction inside the construction of the Doc class. Is there a specific or maybe an alternative way to do this? (sorry if this task is kind of elementary, but I am still very newbie in C++)
Your constructor:
CModel(CMFCApplicationSet ApplicationSet);
takes object of type CMFCApplicationSet by value, meaning that the copy of passed object is created and this copy is then used within its body. When you do the following:
pModelSet = &ApplicationSet;
you are actually storing the addres of temporary object, which is destructed when execution goes out of the scope of the constructor. If you try to dereference this pointer afterwards, it will produce undefined behavior.
Some might suggest you to pass a pointer, but if you look at your CModel class closely, you will see that it has only one constructor and it takes the PessoaSet object, i.e. the instance of CModel requires the existance of some object of type PessoaSet, i.e. you should keep a reference, not a pointer:
class CModel
{
public:
CModel(CMFCApplicationSet& ApplicationSet) : modelSet(ApplicationSet) { }
CMFCApplicationSet& modelSet;
}
and in the other class that contains instance of CModel:
class CMFCApplicationDoc
{
public:
CMFCApplicationDoc() :
Model(m_MFCApplicationSet) { }
CMFCApplicationSet m_MFCApplicationSet;
CModel Model;
}
just note that the order, in which members of CMFCApplicationDoc are declared actually matters here, since you want m_MFCApplicationSet to be initialized earlier than Model and the standards (12.6.2 §5) says: "nonstatic data members shall be initialized in the order they were declared in the class definition".
Related
I want to use a class: class2, within a class: class1. From what I read, to prevent a circular dependency, one must forward declare class2 in class1.h and have it be a pointer. After calling a function from class2 in my class1.cpp file. I'm unable to call the variables within class2 without getting "Unable to read memory" or a nullptr.
Here's my code, thank you for the help:
//main.cpp
#include "Login.h"
#include <iostream>
using namespace std;
int main() {
Login login;
login.StartMenu();
cout << "ENDING" << endl;
system("pause");
return 0;
}
//Login.h (Class1)
#pragma once
#include <iostream>
using namespace std;
class GameManager;
class Login {
public:
void StartMenu();
private:
GameManager* manager;
};
//Login.cpp
#include "Login.h"
#include "GameManager.h"
void Login::StartMenu() {
manager->GameStart();
}
//GameManager.h (Class2)
#pragma once
class GameManager {
public:
void GameStart();
private:
int level = 1;
};
//GameManager.cpp
#include "Login.h"
#include "GameManager.h"
void GameManager::GameStart() {
cout << level;
}
Generally, it is a good idea to keep dependencies between headers to a minimum, and using pointers for classes that are only forward-declared is an established way to do that. This is good practice even if there are no circular dependencies because it can greatly reduce recompilation times in large projects.
Regarding your specific question: Essentially, the Login class, and especially the Login::StartMenu function, needs to know which GameManager instance to use. A pointer to that instance will be stored in manager. Ideally you can tell that at construction time of a Login instance via a GameManager * constructor argument:
#ifndef LOGIN_H
#define LOGIN_H
class GameManager;
/// This class handles the login procedure for a specific
/// game manager which must be provided to the constructor.
/// It cannot be copied (so it cannot be
/// in arrays) or default-constructed.
class Login {
public:
/// The constructor does nothing except initializing manager.
/// #param gmPtr is a pointer to the game manager
/// this instance is using.
void Login(GameManager *gmPtr)
: manager(gmPtr) { /* empty */ }
void StartMenu();
private:
GameManager* manager;
};
#endif // LOGIN_H
For completeness, here is how you would use it:
#include "Login.h"
#include "GameManager.h"
#include <iostream>
using namespace std;
int main() {
GameManager gm;
Login login(&gm); // <-- provide game manager to login
login.StartMenu();
cout << "ENDING" << endl;
system("pause");
return 0;
}
If that is not possible because the GameManager instance does not exist yet or is otherwise unknown during construction of a Login instance (for example, if you have an array of Login instances, whose elements must be default-constructed) you can provide the argument to the Login::StartMenu method. But the constructor argument is much preferred because you can then be sure that the class is functional in the rest of the code — this kind of "invariants" are the main reason why constructors exist.
It is certainly possible that you don't need to hold a pointer at all, if all functions get that pointer argument. Whether the Login class has a one-to-one relationship with a GameManager (in which case it simply holds a pointer to it) or not (in which case every function is told each time) is a design decision.
This question comes from this question.
Im trying to implement the state pattern with a shared_ptr to the container(game).
However I have a problem with circular inclusion and need to forward declare.
My code:
Game.h
#pragma once
#include <memory>
#include "BaseState.h"
class Game : public std::enable_shared_from_this<Game>
{
private:
std::shared_ptr<BaseState> currentState;
public:
Game();
void switchState(std::shared_ptr<BaseState> nextState);
void doSomething(char);
void runState();
};
cpp
#include "stdafx.h"
#include <iostream>
#include "Game.h"
#include "SomeState.h"
Game::Game()
{
currentState = std::make_shared<SomeState>();
}
void Game::switchState(std::shared_ptr<BaseState> nextState)
{
currentState = nextState;
}
void Game::doSomething(char c)
{
std::cout << "Game : " << c;
}
void Game::runState()
{
currentState->handleCommand(shared_from_this());
}
BaseState.h
#pragma once
#include <memory>
#include "Game.h"
class BaseState
{
public:
virtual void handleCommand(std::shared_ptr<Game>) = 0;
};
SomeState.h
#pragma once
#include "BaseState.h"
class SomeState :
public BaseState
{
public:
// Inherited via BaseState
virtual void handleCommand(std::shared_ptr<Game>) override;
};
cpp
#include "stdafx.h"
#include "SomeState.h"
void SomeState::handleCommand(std::shared_ptr<Game> game)
{
game->doSomething('S');
}
I read other questions about forward declaring but still don't get it.
What I tried;
forward declare BaseState in Game, the code compiles but throws an error.
Unhandled exception at 0x73E9DAE8 in ConsoleApplication1.exe:
Microsoft C++ exception: std::bad_weak_ptr at memory location
0x00BBF5D4.
Forward declare Game in BaseState. Dosnt compile gives use of undefined type error, also
'doSomething': is not a member of
'std::shared_ptr'
which is logic because at compile time game has not a doSomething function because forward declared like;
class Game;
How do I decide where to forward declare another class, are there any logical steps or should I just pick one and fix the problems that choise creates?
You don't need to #include <Game.h> in BaseState.h, you can simply forward-declare it
class Game;
This works because the BaseState declaration doesn't need to know the contents of Game. So what you tried first is OK. The same applies to #include <BaseState.h> in Game.h. Replace that with a forward-declaration of BaseState.
The std::bad_weak_ptr exception was due to something else. Specifically, you're probably missing the little detail about shared_from_this, which says
It is permitted to call shared_from_this only on a previously shared
object, i.e. on an object managed by std::shared_ptr. Otherwise the
behavior is undefined
and
(from C++17) std::bad_weak_ptr is thrown (by the
shared_ptr constructor from a default-constructed weak_this)
You can usually solve this by instantiating your object into a shared_ptr:
int main() {
auto myGame = std::make_shared<Game>();
. . .
myGame->runState();
. . .
}
EDIT
Keep in mind though, that shared_ptr has a certain cost associated with using it. In general, if you know the pointed-to object always outlives the function call where it is used, as might be the case with your BaseState::handleCommand, then it may be faster (and still safe) to just pass it by reference.
I keep having problems with this. If I define an object in main.cc, how do I access that object from another .cc file?
main.cc:
#include "Class.h"
#include "header.h"
int main()
{
Class object;
return 0;
}
file.cc:
#include "header.h"
void function()
{
object.method(parameter);
}
What would I have to put in header.h to get this working? Any help would be appreciated.
how do I access that object from another .cc file?
What would I have to put in header.h to get this working?
The simple answer to is to "pass the object by reference".
An object created in main() lasts for the entire program. This is typical in embedded systems ... I have no issues with this aspect.
I would, however, put the long lasting object in dynamic memory (because the stack is more limited).
main.cc:
#include "Class.h"
#include "header.h"
int main()
{
Class* object = new Class;
function(*object); // <--- pass the object by reference
return 0;
}
file.cc:
#include "Class.h"
#include "header.h"
void function(Class& object) // <-- how to specify reference
{
object.method(parameter); // <-- you did not identify parameter
}
header.h
class Class; // <--- poor name choice
void function (Class& object); // <--- another poor name choice
// note that the compiler needs to know only that Class is a
// user defined type -- the compiler knows how big a reference
// or ptr to the class is, so you need not provide more Class info
// for this file
Of course, you still need to write Class.h and define Class
Update - You have marked this post as C++.
So, please consider the following (which sidesteps the pass by reference dilemma):
main.cc:
#include "Class.h"
#include "header.h"
int main()
{
Class* object = new Class;
//
// I recommend you do not pass instance to function.
//
// Instead, the C++ way is to invoke an instance method:
object->function();
// and, if you've been paying attention, you know that the method
// Class::function()
// has access to the 'this' pointer of the class
// and thus the 'passing' of this instance information
// is already coded!
// some of your peers would say you must:
delete object;
// others would say this is already accomplished by the task exit.
return 0;
}
If you were to try something like...
file.cc:
#include main.cc
The compiler would be compiling main.cc twice -- which means it would see 2 definitions of everything in main.cc. This will cause you some problems.
It's better design (and actually compiles correctly! Bonus!) to create a custom header file for your classes, and then import this as necessary.
myclasses.h:
Class object;
file.cc:
#include myclasses.h
This should be a C++ specific.
I have a property m9ReloadAnim in the header file, I can access it from the constructor, but when I try to access it from an other function I get an error like: EXC_BAD_ACCESS or something like: "The address does not contain an object ".
I have a header class like this:
#ifndef __SWAT__Weapon__
#define __SWAT__Weapon__
#include "cocos2d.h"
class Weapon : public cocos2d::CCSprite
{
private:
cocos2d::CCAnimation *m9ReloadAnim = cocos2d::CCAnimation::create();
public:
Weapon();
~Weapon();
void reloadM9();
};
#endif
And a cpp file like this:
enter code here
#include "Weapon.h"
#include "cocos2d.h"
Weapon::Weapon(){
m9ReloadAnim->setDelayPerUnit(1.1f);
}
Weapon::~Weapon(){
}
void Weapon::reloadM9(){
m9ReloadAnim->setDelayPerUnit(1.1f);
}
You could not initialize variable like this:
cocos2d::CCAnimation *m9ReloadAnim = cocos2d::CCAnimation::create();
Only static const int could be init in class declaration.
Move this init to your ctor:
Weapon::Weapon()
: m9ReloadAnim(cocos2d::CCAnimation::create())
{
m9ReloadAnim->setDelayPerUnit(1.1f);
}
or
Weapon::Weapon()
{
m9ReloadAnim = cocos2d::CCAnimation::create();
m9ReloadAnim->setDelayPerUnit(1.1f);
}
Sometimes the becomes corrupted so you can't tell where errors originate. I would suggest to put a breakpoint at the entry point of each method, and step the code line by line to make sure that it's triggering in the reloadM9 method. Check to see the m9ReloadAnim is NULL or if it points to the object created at initialization. Additionally you need to check if you are using the library properly.
I need to call properties and functions of an object from a different class.
The idea is passing 'this' as a parameter to the other class constructor. E.g.:
instance = ClassName(this);
And then do:
ParentClass parentInstance;
ClassName::ClassName(MainApp _instance){
parentInstance = _instance;
}
However, my compiler says that ParentClass does not name a type. Ideas?
Also, should I use a pointer to save memory? How?
Thanks in advance.
UPDATE:
Ok, sorry for the delay. Here it goes the actual code. First, a simple class.
Game class:
Header file
#ifndef _GAME
#define _GAME
#include "ofMain.h"
class Game{
public:
Game();
~Game();
void hi();
};
#endif
cpp file:
#include "Game.h"
Game::Game(){}
Game::~Game(){}
void Game::hi(){
cout << "hi, I'm game! " << endl;
}
Then, from MainApp I create the object:
- Relevant code on header file:
#ifndef _MAIN_APP
#define _MAIN_APP
#include "ofMain.h"
#include "Game.h"
class MainApp : public ofSimpleApp{
public:
Game game;
};
#endif
Relevant code on the cpp file:
game = Game();
game.hi();
This obviously works as I'm only creating a bloody object. However, problem comes with composition.
I could pass the main app as argument in the constructor, I could pass it via game.setParent(this);... problem is, I can't even define the variable to store the reference to the app.
E.g.: (making it easy/inefficient without pointers or anything)
Game.h:
#define _GAME
#ifndef _GAME
#include "ofMain.h"
#include "MainApp.h"
class Game{
MainApp app;
public:
Game();
~Game();
void hi();
};
#endif
This returns a "does not name a type" error and declaring class MainApp returns an "incomplete type" error
I'm sure I'm doing something dumb.
UPDATE 2:
The problem with that method is that I can't call a function of the pointed object now.
This is Game.h:
#ifndef _GAME
#define _GAME
#include "ofMain.h"
class MainApp;
class Game{
public:
Game();
Game(MainApp* _app);
~Game();
void hi();
MainApp* app;
};
#endif
As you see, app (of the type MainApp) is passed as a parameter. That's fine, MainApp exists as it's the forward declaration. However, when I try to call any of app's functions I can't (compiler error saying Request for member appHi in .... which is non-class type 'MainApp'.
MainApp is NOT included in Game.h but Game.h IS included in MainApp.h.
Ideas?
The problem is you have a circular reference - Game includes MainApp, and MainApp includes game. You need a 'forward declaration', as per the example by DeadMG.
See here.
It's called composition and is a common pattern. It's highly efficient in both semantics and in terms of runtime speed/memory footprint.
Your code example is a little too much pseudocode for me to read it correctly. Let me show you how it's done.
class X;
class Y {
...
void DoSomething(X* x, ... args);
};
class X {
Y y;
void DoSomething() {
y.DoSomething(this, args);
}
};
I think there may be two issues here:
1) You need to declare the ParentClass (i.g. #include its .hpp-file) before using it
2) The assignment "parentInstance = _instance" will invoke the assignment operator, which i'm guessing is not what you want. let "parentInstance" be a pointer instead.
Note the section on "#include."
http://www.cplusplus.com/doc/tutorial/program_structure/
After the "Intro to the C++ Language" section look for the verbiage about #include.
http://www.cprogramming.com/tutorial/lesson1.html
Namespaces:
http://www.tenouk.com/Module23.html
HTH
That's not how things work in C++. Unlike javascript, you cannot inject methods or fields into existing objects at runtime.
Madsen is on the right track here, but we need more code; What is the class heirarchy of ParentClass, ClassName and SaleraApp. Which classes are base and/or dervied?
When you write: parentInstance = _instance; the compiler will try to generate a default copy constructor if one is not defined. Your problem might be that you are trying to create a dervied class object from a base class pointer.
Also, "this" is a pointer.
If all you need to do is use functions and data members of another class, read up on the friend keyword. It will allow access to class members from other classes.
UPDATE: Alternatively, store a pointer or reference to the object you need access to, and make getters for data members and make the functions public... but I get the feeling this is not what you're after...