Hi folks, I tried to read some past threads in this forum but I didn't find one that solves the problem I'm dealing about.
I have experience with Java/OO programming and I'm developing a project using C++ (I have some background with C/C++ programming but I'm messing around some issues of the C++ language).
Well let's go to the problem:

My application uses the Model/View/Controller pattern and since I'm trying to add a ProgressBar to my "View" module I'm using the Observer Pattern, so I created two classes (I'd refer it as "interfaces")

class AbstractObserver {
public:
    virtual void update(int progressStatus) = 0;

};
class AbstractSubject {
public:
	virtual void registerObserver(AbstractObserver* observer) = 0;
	virtual void removeObserver(AbstractObserver* observer) = 0;
	virtual void notifyObserver() = 0;
};

Since my "View"class (named IMDialog) is the Observer, it extends the "AbstractObserver" class, and so implements the "update(int progressStatus)" method. Ex:

#include "AbstractObserver.h"
#include "IupDialogWrapper.h"

class IMDialog : public AbstractObserver, public IupDialogWrapper {
public:
	void update(int progressStatus) {
		cout << "IMDialog: " << progressStatus << endl;
	}

       // another methods of the IupDialogWrapper class..
}

In another class, such as the controller class, I did a simple test, trying to invoke the method in the following way:

IMDialog *frontEnd = new IMDialog();
frontEnd->update(42);

The code compiles and links perfectly, but when the method "void update(int progressStatus)" is called the application terminates with an error. (actually it is not been called).

I realized that if I make another class as the Observer, which has the signature:

class AnotherClass: public AbstractObserver { 
public:
	void update(int progressStatus) {
		cout << "AnotherClass: " << progressStatus << endl;
	}
};

the method "void update(int progressStatus)" can be invoked, is it a problem of "multiple inheritance" or something like this? The way I'm invoking the method "frontEnd->update(42);" is wrong? I tried doing some cast, as well as dynamic_cast<>() with no sucess.

Sorry for the whole history, but I tried to explain the plot.

Thanks,
Eduardo

Recommended Answers

All 8 Replies

I don't think you can't assign values to functions/methods.

I don't know what you want to do but as I see it you use the assignment as a way to make the method do nothing until you find out how to implement the method.

To do this in C++ you can just add an empty body either in the class declaration or in the definition then you can redefine it later

>>don't think you can't assign values to functions/methods.
That is how to create a pure virtual function

A pure virtual function or pure virtual method is a virtual function that is required to be implemented by a derived class that is not abstract. Classes containing pure virtual methods are termed "abstract;" they cannot be instantiated directly, and a subclass of an abstract class can only be instantiated directly if all inherited pure virtual methods have been implemented by that class or a parent class. Pure virtual methods typically have a declaration (signature) and no definition (implementation) .

eduardocoelho: you need to declare the implementation of a virtual function exactly as it is in the base class, but without the "=0". The simplest way to get this right is to just copy/paste from base class to derived class.

#include "AbstractObserver.h"
#include "IupDialogWrapper.h"

class IMDialog : public AbstractObserver, public IupDialogWrapper {
public:
	virtual void update(int progressStatus) {
		cout << "IMDialog: " << progressStatus << endl;
	}

       // another methods of the IupDialogWrapper class..
}

1. Next time use code tag with the language specifier:
[code=c++] source(s)

[/code]
2. No need to repeate virtual specifier in derived classes.
3. >when the method "void update(int progressStatus)" is called the application terminates with an error.
Can't reproduce errors, it works as expected. No problems.
4. You must declare virtual destructor for abstract class (to invoke right derived class destructor)
5. See what you may expect from all these mechanics:

class AbstractObserver {
public:
    virtual ~AbstractObserver() {} // Add this!
    virtual void update(int progressStatus) = 0;

};

class AbstractSubject { // Don't know what to do with this class now...
public:
    virtual ~AbstractSubject() {} // Add this!
    virtual void registerObserver(AbstractObserver* observer) = 0;
    virtual void removeObserver(AbstractObserver* observer) = 0;
    virtual void notifyObserver() = 0;
};

class IMDialog : public AbstractObserver {  //, public IupDialogWrapper {
public:
    void update(int progressStatus) { // It's virtual!
         cout << "IMDialog: " << progressStatus << endl;
    }
       // another methods of the IupDialogWrapper class..
};

class AnotherClass: public AbstractObserver { 
public:
    void update(int progressStatus) {
         cout << "AnotherClass: " << progressStatus << endl;
    }
};

int main()
{
    AbstractObserver* frontEnd = new IMDialog();
    frontEnd->update(42);
    delete frontEnd;

    frontEnd = new AnotherClass();
    frontEnd->update(43);
    delete frontEnd;

    return 0;
}

1. Next time use code tag with the language specifier:
[code=c++] source(s)

[/code]

c++ has been depreciated. use [code=cplusplus]

c++ has been depreciated. use [code=cplusplus]

It's a pity...
I hate this awful pseudoword ;)...

1. Next time use code tag with the language specifier:
[code=c++] source(s)

[/code]
2. No need to repeate virtual specifier in derived classes.
3. >when the method "void update(int progressStatus)" is called the application terminates with an error.
Can't reproduce errors, it works as expected. No problems.
4. You must declare virtual destructor for abstract class (to invoke right derived class destructor)
5. See what you may expect from all these mechanics:

class AbstractObserver {
public:
    virtual ~AbstractObserver() {} // Add this!
    virtual void update(int progressStatus) = 0;

};

class AbstractSubject { // Don't know what to do with this class now...
public:
    virtual ~AbstractSubject() {} // Add this!
    virtual void registerObserver(AbstractObserver* observer) = 0;
    virtual void removeObserver(AbstractObserver* observer) = 0;
    virtual void notifyObserver() = 0;
};

class IMDialog : public AbstractObserver {  //, public IupDialogWrapper {
public:
    void update(int progressStatus) { // It's virtual!
         cout << "IMDialog: " << progressStatus << endl;
    }
       // another methods of the IupDialogWrapper class..
};

class AnotherClass: public AbstractObserver { 
public:
    void update(int progressStatus) {
         cout << "AnotherClass: " << progressStatus << endl;
    }
};

int main()
{
    AbstractObserver* frontEnd = new IMDialog();
    frontEnd->update(42);
    delete frontEnd;

    frontEnd = new AnotherClass();
    frontEnd->update(43);
    delete frontEnd;

    return 0;
}

mostermand:
I'm defining a pure virtual function, as explained by Ancient Dragon.

Ancient Dragon:
The fact or including the "virtual" specifier in front of the method signature didn't make it to work.

ArkM:
Thanks, you'll follow your advices when posting a new thread.
I added the virtual destructors as you suggested, but I think it is not the main point. I still have no sucess while trying to invoke the "update" method.
I tried to declare the object front end in the way you suggested, such as:

AbstractObserver* frontEnd = new IMDialog();

I am still getting no success. As I can see, you redefined the "IMDialog" class in a different way that makes no sens for my application, you removed the " public IupDialogWrapper {" inheritance definition, but this class specifies my user interface an I have to extend it.
As I said, if I have a simple class which simples extends the "AbstractObserver" abstract class it works well, I already tested it. The problem is that the "IMDialog" must extends both "AbstractObserver" and "IupDialogWrapper" classes, wouldn't it be causing the problem?

Thanks,
Eduardo

I'll post all the class codes so that it becomes clearer to understand:

My compiler version: gcc version 3.4.5 (mingw-vista special r3).

My super-classes are:

AbstractObserver.h

class AbstractObserver {
public:
    virtual void update(int progressStatus) = 0;
};

AbstractSubject.h

#include "AbstractObserver.h"

class AbstractSubject {
public:
	
	virtual void registerObserver(AbstractObserver* observer) = 0;

	virtual void removeObserver(AbstractObserver* observer) = 0;

	virtual void notifyObserver() = 0;
};

IupDialogWrapper.h

// This class is a wrapper for the User interface API that I'm using which need C callbacks (that I 
// implemented as friend functions.
#include <stdlib.h>
#include <iostream>
#include <iup.h>
#include "IMDefs.h"

using namespace std;

namespace view {

class IupDialogWrapper {
public:
// constructors..

protected:
       // some class attributes..
       // some class member functions, Ex:
       void showDialog(int x, int y);
       virtual int callbackResize(Ihandle *self, int w, int h) { return IUP_DEFAULT; }
       virtual int callbackShow(Ihandle *self, int state) { return IUP_DEFAULT; }
       
private:
       friend int IMV_IupDialogWrapper_callbackDialogResize(Ihandle* self, int w, int h);
};
}

IupDialogWrapper.cpp

#include "IupDialogWrapper.h"
#include "Controller.h"

namespace view {

void IupDialogWrapper::showDialog(int x, int y) { /* code.. */ }

int IMV_IupDialogWrapper_callbackDialogResize(Ihandle *self, int w, int h) {  /* code.. */ }

// The virtual member functions are defined in the subclass (see IMDialog class below)
}

The classes who extends these abstract classes are:

IMDialog.h

#include "AbstractObserver.h"
#include "IupDialogWrapper.h"

namespace view {
class IMDialog : public AbstractObserver, public IupDialogWrapper {
public:
void update(int progressStatus); // supposed to be from AbstractObserver abstract class

protected:
int callbackResize(Ihandle *self, int w, int h);
int callbackShow(Ihandle *self, int state);
};
}

IMDialog.cpp

#include "IMDialog.h"
#include "Utils.h"

namespace view {
int IMDialog::callbackResize(Ihandle *self, int w, int h) { /* code.. */  }
int IMDialog::callbackShow(Ihandle *self, int state) { /* code.. */  }
}

void IMDialog::update(int progressStatus) {
	cout << "IMDialog: " << progressStatus << endl;
}
}

Mosaic.h // this class is running ok, but I'll post here just for clarification

#include "AbstractSubject.h"

using namespace std;

namespace model {
class Mosaic : public AbstractSubject {
public:
       // constructors..etc

       void registerObserver(AbstractObserver* observer);
       void removeObserver(AbstractObserver* observer);

private:	
	void notifyObserver();

private:
        list<AbstractObserver* > observers;
};
}

Mosaic.cpp

#include "Mosaic.h"

using namespace std;

namespace model {
void Mosaic::registerObserver(AbstractObserver* observer) {
	this->observers.push_back(observer);
}

void Mosaic::removeObserver(AbstractObserver* observer) {
	this->observers.remove(observer);
}

void Mosaic::notifyObserver() {
	list<AbstractObserver*>::iterator it = this->observers.begin();
	while (it != this->observers.end()) {
               
// HERE IS THE PROBLEM!!!!!!!
// The method below is not being called!
// If the IMDialog class only inherits from AbstractObserver it works, but since it
// also inherits from IupDialogWrapper it seem's not be working!
               
		((AbstractObserver*) (*it))->update(this->mosaicingProgressStatus);
		++it;
	}

}
}

The IMDialog class instantiation as well as registering inside the Mosaic object is as follows

Controller.h

#include "IMDialog.h"
namespace view {
	class IMDialog;
}
#include "AbstractObserver.h"
#include "Mosaic.h"

namespace controller {
class Controller {
public:
     // constructors, etc
     bool createMosaic(/* parameters */);

private:
	AbstractObserver *frontEnd;
};
}

Controller.cpp

#include "Controller.h"

namespace controller {
bool Controller::createMosaic(/* parameters */ ) {

        this->frontEnd = new view::IMDialog(this);
	this->mosaic = new model::Mosaic(/* parameters */);

// !!!
// Registering the frontEnd object as a observer o the Mosaic object.
// The mosaic object in a future time will start some processing and consequently 
// will try to call the "update" method of the frontEnd object (as described inside the "void
// Mosaic::notifyObserver() {} method"
	this->mosaic->registerObserver(this->frontEnd);

// I also tried to make a simple call here inside this method, such as:
       frontEnd->update(42);

// but it didn't work (of course, if it works here it will work inside the "void Mosaic::notifyObserver() {} method" too

// some application stuff..
	return this->mosaic->create();
}
}

Well, It seems like a lot of code, maybe there's another way to explain what I trying to do, I posted all the code in order not to miss any information about the #includes and method/classes signatures.
I'm compiling and linking with sucess:

============================================
g++ -IC:\tcc\dev\libs\eclipse\iup3_0_beta2_Win32_mingw3_lib\include -IC:\tcc\dev\libs\eclipse\cd5_1_1_Win32_mingw3_lib\include -IC:\tcc\dev\libs\eclipse\im3_4_1_Win32_mingw3_lib\include -O0 -g3 -Wall -c -fmessage-length=0 -osrc\Mosaic.o ..\src\Mosaic.cpp

// ...
// another source files compilation, similarly

g++ -LC:\tcc\dev\libs\eclipse\iup3_0_beta2_Win32_mingw3_lib -LC:\tcc\dev\libs\eclipse\cd5_1_1_Win32_mingw3_lib -LC:\tcc\dev\libs\eclipse\im3_4_1_Win32_mingw3_lib -oImageMosaicing.exe src2\MatrixTemplate.o src2\ImageMosaicing.o src2\IMMosaic.o src\main.o src\Vector.o src\Mosaic.o src\Matrix.o src\ManipulableObject.o src\IupDialogWrapper.o src\IMImage.o src\IMDialog.o src\Homography.o src\CorrespondencePointMark.o src\CorrespondencePoint.o src\Controller.o -liupcd -lcd -liup -lgdi32 -lcomctl32 -lole32 -lcomdlg32 -lfreetype6 -lim
Build complete for project ImageMosaicing
Time consumed: 7751 ms.
============================================

The problem occurs in runtime !

Best regards,
Eduardo

mostermand:
I'm defining a pure virtual function, as explained by Ancient Dragon.

Ancient Dragon:
The fact or including the "virtual" specifier in front of the method signature didn't make it to work.

ArkM:
Thanks, you'll follow your advices when posting a new thread.
I added the virtual destructors as you suggested, but I think it is not the main point. I still have no sucess while trying to invoke the "update" method.
I tried to declare the object front end in the way you suggested, such as:

AbstractObserver* frontEnd = new IMDialog();

I am still getting no success. As I can see, you redefined the "IMDialog" class in a different way that makes no sens for my application, you removed the " public IupDialogWrapper {" inheritance definition, but this class specifies my user interface an I have to extend it.
As I said, if I have a simple class which simples extends the "AbstractObserver" abstract class it works well, I already tested it. The problem is that the "IMDialog" must extends both "AbstractObserver" and "IupDialogWrapper" classes, wouldn't it be causing the problem?

Thanks,
Eduardo

>I also tried to make a simple call here inside this method, such as: frontEnd->update(42); but it didn't work
The fact that IMDialog also inherits from the IupDialogWrapper does not bear a relation to its is_an AbstractObserver characteristic. The fact that no visual effect after update call does not bear a relation to this polymorphic mechanics. For example, may be it's an error in your indirect path to the visual interface.
Regrettably, it didn't work is not a diagnosis, it's a vague symptom only.

Once again: define an abstact class destructor as virtual!!!

I'll try to analyse your code later...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.