Virtual methods and subclasses in c++ - c++

So i'm trying to better understand virtual methods.
I have a base class Sensor and several subclasses SensorTemp *SensorPh* SensorOrp
class Sensor
{
public:
virtual void updateValue();
}
the subclasses then override updateValue with their own method definitions (this happens in each of the subclasses)
.h file
#include "Sensor.h"
class SensorTemp : public Sensor
{
private:
public:
};
.Cpp file
#include "Sensor.h"
#include "SensorTemp.h"
void Sensor::updateValue(){
int reading = analogRead(pinId);
float voltage = reading * 5.0;
voltage /= 1024.0;
currentVal = voltage * 100 ;
Serial.print("temp: "); Serial.println(currentVal);
}
My issue is this works for the first subclass declaration, although the following will have a compiler error: updateValue() .... first defined here ld.exe : : Disabling relaxation: it will not work with multiple definitions
So I'm stuck on what type of approach I should take if I want to define the method differently from each subclass?
Any insight would be highly appreciated!

You subclass implementation should look like:
void SensorTemp::updateValue() {
// ...
}

It seems you are trying to learn dynamic dispatch through virtual keyword. In dynamic dispatch the actual type of object determines the appropriate method from that class to be called. To achieve this, the base class should provide a virtual method and each of the sub-classes should overrie that virtual method to provide their own behavior.
So each of your subclass should override the virtual method.
//.h file
class SensorTemp : public Sensor
{
private:
public:
virtual void updateValue();
};
//.cpp file
void SensorTemp::updateValue()
{
// ....
}
If your sub-classes do not override the virtual method then irrespective of the actual type of the object(be it base or sub-class) the Base class virtual method will be called.

Related

Design pattern: inheritance and encapsulated inheritance

I got problems formulating it precisely so I left more general description in the title (if you have more precise description of the problem, please comment, I'll edit the title).
The problem: Two classes AudioStream and VideoStream are derived from base class MediaStream which has some common for audio and video stream methods, but is not intended to be used as-is. Consequently, there are two classes AudioStreamSettings and VideoStreamSettings which are derived from MediaStreamSettings and passed to the constructors of their corresponding stream classes. MediaStreamSettings stores settings common for audio and video, and base class MediaStream accesses this data. The question is: what would be the best way to design this hierarchical relationship between base classes of streams and settings?
I can think of a quick solution like the following:
class MediaStream {
public:
MediaStream(const MediaStreamSettings& settings){
// do nothing, let derived classes initialize settings_
// note: I feel guilty for doing this...
}
virtual ~MediaStream(){}
protected:
std::shared_ptr<MediaStreamSettings> settings_;
};
class VideoStream : public MediaStream {
public:
VideoStream(const VideoStreamSettings& settings):
MediaStream(settings)
{
settings_ = std::make_shared<VideoStreamSettings>(settings);
}
void doSomething(){
int s1 = std::dynamic_pointer_cast<VideoStream, MediaStream>(settings_)->getVideoStreamSetting1();
...
}
};
class AudioStream : public MediaStream {
public:
AudioStream(const AudioStreamSettings& settings):
MediaStream(settings)
{
settings_ = std::make_shared<AudioStreamSettings>(settings);
}
}
To summarize I'm not comfortable with two things in this approach:
not initializing settings_ in base class (should I make it abstract to calm myself?)
using dynamic_pointer_cast every time I need to access settings in derived classes (should I make a method wrapper for this?)
One solution is to not store data in MediaStream and add a virtual method
virtual const MediaStreamSettings& GetMediaStreamSettings() const = 0;
Since MediaStream should not be used as-is, making it an abstract class should be acceptable (and desirable).
Thus providing implementation (which includes class members) is pointless.
class IMediaStream {
public:
virtual ~IMediaStream() {}
virtual void play() = 0;
virtual std::shared_ptr<MediaSettings> getSettings() = 0;
private:
IMediaStream() {}
};
template<Setting>
class MediaStream : public IMediaStream {
public:
MediaStream(const Setting& settings){
settings_ = std::make_shared<Setting>(settings);
}
virtual ~MediaStream() {}
virtual void play() override {
// Implementation here
}
virtual std::shared_ptr<MediaSettings> getSettings() override {
return std::dynamic_pointer_cast<Setting, MediaSettings>();
}
private:
std::shared_ptr<Setting> settings_;
}
// Alternatively you can inherit or specialize
// the template to add your implementation
typedef MediaStream<VideoStreamSettings> VideoStream;
typedef MediaStream<AudioStreamSettings> AudioStream;

C++ Interface issues with creating an instance of it

So i have an assignment in my C++ class that is asking me to create an abstract base class called Project, and an interface called Task. Now he gave us the driver code for the main, and within it it's asking us to create an instance of the interface "Task", and i keep getting an error saying " you cant create an instance of an abstract base class" Here's my "Task" interface header file and the main.. I hope it's enough.
#pragma once
#ifndef TASK_h
#define TASK_h
class Task
{
public:
Task();
virtual ~Task();
virtual void addPrereq(Task *pt) = 0;
virtual bool ready() = 0;
virtual bool done() = 0;
virtual void doIt() =0;
};
#endif
And the main:
#include "stdafx.h"
#include "CompositeProject.h"
#include "MinorProject.h"
#include "SimpleProject.h"
#include "Task.h"
int _tmain(int argc, _TCHAR* argv[])
{
// Create tasks
Task* tasks[7];
for (int i = 0; i != 7; ++i)
tasks[i] = new Task();//This is where my error is coming from
// Set prerequisites
tasks[1]->addPrereq(tasks[0]);
tasks[2]->addPrereq(tasks[1]);
tasks[3]->addPrereq(tasks[2]);
tasks[3]->addPrereq(tasks[4]);
tasks[4]->addPrereq(tasks[0]);
tasks[5]->addPrereq(tasks[4]);
tasks[6]->addPrereq(tasks[3]);
tasks[6]->addPrereq(tasks[5]);
return 0;
}
Now to my knowledge the difference between an abstract base class and an Interface is that the abstract base class normally has a protected constructor, and has atleast one pure virtual method. Now an interface has all it's methods pure virtual, to essentially have a template. Now i don't understand how or why my teacher is asking us to create an instance of the interface Task. He explicitly says elsewhere in the assignment, expected files " Task.h and Task.cpp ". I feel like there's a key element I'm missing here. Thanks!
By default you can not create an object of an abstract base class because the ABC acts like a blueprint on which you create your actual implementation. To give you an example you can define a Shape abstract base class that has a method called virtual void form()=0; for redefining the form of some geometric shape and on that class you can define another class called Cube and another one calledCirclebut each one of those classes have inherited the void form(); function which you need to redefine for both Cube and Circle classes...so going back to your problem the abstract class should be called Project (as you are saying) and your code should look something like this
#ifndef TASK_H
#define TASK_H
class Project { //project is the abstract base class
public:
Project();
virtual ~Project();
virtual void addPrereq(Project *pt) = 0;
virtual bool ready() = 0;
virtual bool done() = 0;
virtual void doIt() =0;
};
class Task:public Project {
Task();
virtual ~Task();
virtual void addPrereq(Task *pt);
virtual bool ready();
virtual bool done();
virtual void doIt();
}
#endif // PROJECT_H
In conclusion:
when a class declaration contains a pure virtual function, you can't create an object of that class.
any method in ABC that is not virtual is inherited like it is defined, if you have a void move(); function in the Shape class then you can use the function in all inherited classes so you don't need to declare all the functions virtual
An ABC describes an interface that uses a least one pure virtual function, and clases derived from an ABC use regular virtual functions to implement the interface in terms of the properties of the particular derived class

public inherited class not able to access overloaded non-virtual public method of base class?

My compiler says:
error C2660: 'UberMaterial::Initialize' : function does not take 2 arguments
When I write this:
#include "BaseMaterial.h"
#include "UberMaterial.h"
UberMaterial* m_pGameLevelMaterial;
m_pGameLevelMaterial->Initialize(m_pContentManager, m_pLevel->GetDevice());
The base class:
class BaseMaterial
{
public:
BaseMaterial(tstring shaderFilename);
virtual ~BaseMaterial(){}
void Initialize(ContentManager *pContentManager, ID3D10Device *pD3DDevice);
//[More Code...]
protected:
virtual void Initialize(ContentManager *pContentManager) = 0;
//[More Code...]
};
The inherited class:
#include "BaseMaterial.h"
class UberMaterial:public BaseMaterial
{
//[More Code...]
protected:
virtual void Initialize(ContentManager *pContentManager);
//[More Code...]
};
Can anyone tell me what the problem is?
If you need more code, just comment and I'll post it. But the whole thing is rather large, so I didn't include it at this point.
Yes, by default, an overload in a derived class will hide a different overload from a base class. You can re-expose the base-class overload with using:
class UberMaterial : public BaseMaterial
{
...
public:
using BaseMaterial::Initialize;
virtual void Initialize(ContentManager *pContentManager);
};

Restricting method call to another method

There probably is a fairly simple and straight-forward answer for this, but for some reason I can't see it.
I need to restrict calling methods from a class only to some methods implemented by derived classes of some interface.
Say I have
class A{
public:
static void foo();
};
class myInterface{
public:
virtual void onlyCallFooFromHere() = 0;
}
class myImplementation : public myInterface{
public:
virtual void onlyCallFooFromHere()
{
A::foo(); //this should work
}
void otherFoo()
{
A::foo(); //i want to get a compilation error here
}
}
So I should be able to call A::foo only from the method onlyCallFooFromHere()
Is there a way to achieve this? I'm open to any suggestions, including changing the class design.
EDIT:
So... I feel there's a need to further explain the issue. I have a utility class which interacts with a database (mainly updates records) - class A.
In my interface (which represents a basic database objects) I have the virtual function updateRecord() from which I call methods from the db utility class. I want to enforce updating the database only in the updateRecord() function of all extending classes and nowhere else. I don't believe this to be a bad design choice, even if not possible. However, if indeed not possible, I would appreciate a different solution.
Change the class design - what you want is impossible.
I am unsure of what you are trying to achieve with so little details and I am unable to comment further.
[Disclaimer: this solution will stop Murphy, not Macchiavelli.]
How about:
class DatabaseQueryInterface {
public:
~virtual DatabseQueryInterface() = 0;
virtual Query compileQuery() const = 0; // or whatever
virtual ResultSet runQuery(const Query&) const = 0; // etc
};
class DatabaseUpdateInterface : public DatabaseQueryInterface {
public:
virtual Update compileUpdate() const = 0; // whatever
};
class DatabaseObject {
public:
virtual ~DatabaseObject() = 0;
protected:
virtual void queryRecord(const DatabaseQueryInterface& interface) = 0;
virtual void updateRecord(const DatabaseUpdateInterface& interface) = 0;
};
class SomeConcreteDatabaseObject : public DatabaseObject {
protected:
virtual void updateRecord(const DatabaseUpdateInterface& interface) {
// gets to use interface->compileUpdate()
}
virtual void queryRecord(const DatabaseQueryInterface& interface) {
// only gets query methods, no updates
}
};
So the basic idea is that your DatabaseObject base class squirrels away a private Query object and a private Update object and when it comes time to call the protected members of the subclass it hands off the Update interface to the updateRecord() method, and the Query interface to the queryRecord() method.
That way the natural thing for the subclasses is to use the object they are passed to talk to the database. Of course they can always resort to dirty tricks to store away a passed-in Update object and try to use it later from a query method, but frankly if they go to such lengths, they're on their own.
You could split your project into different TUs:
// A.h
class A
{
public:
static void foo();
};
// My.h
class myInterface
{
public:
virtual void onlyCallFooFromHere() = 0;
}
class myImplementation : public myInterface
{
public:
virtual void onlyCallFooFromHere();
void otherFoo();
};
// My-with-A.cpp
#include "My.h"
#include "A.h"
void myImplementation::onlyCallFooFromHere() { /* use A */ }
// My-without-A.cpp
#include "My.h"
void myImplementation::otherFoo() { /* no A here */ }
You probably know this, but with inheritance, you can have public, protected, and private member access.
If a member is private in the base class, the derived cannot access it, while if that same member is protected, then the derived class can access it (while it still isn't public, so you're maintaining encapsulation).
There's no way to stop specific functions from being able to see whats available in their scope though (which is what you're asking), but you can design your base class so that the derived classes can only access specific elements of it.
This could be useful because class B could inherit from class A as protected (thus getting its protected members) while class C could inherit from the same class A as public (thus not getting access to its protected members). This will let you get some form of call availability difference at least -- between classes though, not between functions in the same class.
This could work.
class myInterface;
class A {
private:
friend class myInterface;
static void foo();
};
class myInterface {
public:
virtual void onlyCallFooFromHere() {callFoo();}
protected:
void callFoo() {A::foo();}
};
Though at this point I think I'd just make A::foo a static of myInterface. The concerns aren't really separate anymore.
class myInterface {
protected:
static void foo();
};
Is there a reason foo is in A?

How can I resolve interface method and base class method name conflict in C++ Builder?

I have the following abstract base class, SettingsInterface, that I use as an interface:
class SettingsInterface
{
public:
virtual void Refresh() = 0;
virtual void Update() = 0;
virtual void OnConnect() = 0;
virtual void OnDisconnect() = 0;
};
I'm trying to implement this interface in my class below, which inherits from TFrame. TFrame inherits from another class that also has a virtual method called Update.
class DebugSettingsFrame : public TFrame, public SettingsInterface
{
//a bunch of IDE-managed components - left out for brevity
public:
virtual void Refresh();
virtual void Update();
virtual void OnConnect();
virtual void OnDisconnect();
};
When I compile this, I get the error virtual function DebugSettingsFrame::Update() conflicts with base class 'TWinControl'.
I'm stomped on this. How can I resolve this without changing my interface's method definition, Update, to something else?
Edit - Follow-up:
So C++ doesn't have a construct similar to C# where you can explicitly implement interface methods that have the same definition?
Thanks!
Try something like (from the code I can't say exactly):
DebugSettingsFrame::TFrame::Update();
:: is the scope resolution operator. You should be able to specify precisely which version of the function you are calling.
However, note that this is a symptom of a design that may be getting too complex.