I would like to build a simple application framework. The user is supposed to create a class derived from a base class and either use the properties and methods of the base class or override them with his own. Unfortunately, it is not at all clear to me how to instantiate a user class object from my framework library.
// library base class in appframework.hpp
class BasicApp
{
public:
// Initialisation
int initApp();
// Update is called from main loop
int Update();
// Handle input
int KeyInput(u32 KeysDown, u32 KeysHeld, u32 KeysDownRepeat, u32 KeysUp);
};
// user code
#include <appframework.hpp>
class AppMain: public BasicApp
{
// Handle input
int KeyInput(u32 KeysDown, u32 KeysHeld, u32 KeysDownRepeat, u32 KeysUp)
{
if (KeysDown & KEY_A) return 1;
return 0;
}
};
But how will my framework know about the AppMain class? The user should be able to override existing properties and methods and add their own that they can use but that the framework ignores.
I imagine it to be similar to a Java/Kotlin app in Android Studio:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// do whatever you want here
}
}
Are there any similar concepts in C++?
Thank you!
Simply create BasicApp with virtual method and default implementation
class BasicApp {
public:
virtual void onCreate() {/*default*/ }
virtual void onStop() {/*default*/ }
};
Add AppMain that inherits from BasicApp and overrides BasicApp methods. In AppMain there is no override for onStop() that means it will be default.
class AppMain : public BasicApp {
public:
void onCreate() override {
BasicApp::onCreate();//optional to run default aka super in Kotlin
//add your override here
}
};
Unlike Kotlin not calling BasicApp::onCreate() in overriden onCreate will not throw.
Related
As you will soon see, I am not a c++ developer and for this problem I am working on c++ is my only option. I don't mind learning, so just some guidance would be appreciated.
I have a panel class as follows:
class Panel {
... // Methods that implement Panel
virtual void draw() = 0;
... // Other methods to implement Panel
}
And I want two varieties of it so I create two interfaces
class Foo {
virtual void foo() = 0;
}
class Bar: public Foo {
virtual void bar() = 0;
}
I want to pass the implementing class of Foo to other classes and have them only be able to call the method foo, and the same for Bar.
In other languages I could create the class that implements Foo as:
class FooPanel : public Panel, implements Foo{ ... }
or
class BarPanel : public Panel, implments Bar { ... }
then I can pass into a method:
//method(..., foo* pFoo, ...); the signature
method(..., (Foo*)&barPanel, ...);
The only way I can see to accomplish this in c++ is to:
class FooPanel : public Panel {
virtual void foo() = 0;
}
then one has to pass the entire Panel and the implementer is capable of calling and Panel method.
Where can I look to get an idea of how this can be done?
What other languages (such as java) call "interfaces" is just an abstract base class in C++. So if you just replace the implements keyword with public virtual, it will work as you expect:
class FooPanel : public Panel, public virtual Foo { ... }
class BarPanel : public Panel, public virtual Bar { ... }
I have 2 derived classes, in one of these classes I want to customize the implementation of a nested class that is in the base. In the other, I just want to use the base object.
I have encountered a problem that can be demonstrated with below example:
class Widget
{
public:
class Settings
{
// ...
}
// ...
protected:
Settings m_settings;
}
// -------------------------------------------------------
class LimitedWidget : public Widget
{
// ...
// the settings are the same, so using base m_settings object.
}
// -------------------------------------------------------
class SpecialWidget : public Widget
{
public:
class Settings : public Widget::Settings
{
// customize the settings for SpecialWidget
}
// ...
protected:
Settings m_settings; // now I must declare another m_settings object.
}
Uh oh, this is redundant. We already have m_settings defined in our base class Widget, but I don't want to use that in all derived classes (eg. SpecialWidget). I can't make m_settings private in the base class, because I want to use that object in LimitedWidget. But I don't want 2 settings objects, one of which is useless, in SpecialWidget.
Is there a solution?
Thank you for your time.
You could try something like this:
class Widget
{
...
protected:
Settings* m_settings;
public:
void initialize()
{
m_settings = createSettings();
}
protected:
virtual Settings* createSettings()
{
return new Settings();
}
...
} // class Widget
And then:
class SpecialWidget: public Widget
{
public:
class SpecialSettings: public Settings
{
// customize the settings for SpecialWidget
}
protected:
Settings* createSettings()
{
return new SpecialSettings();
}
} // class SpecialWidget
In other words, the base class creates the default settings within the initialize method and your special widget overrides this, creating the special settings.
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;
I want to extract common code from a few WinRT components to one base class so I don't need to copy&past it. I have the following base class:
[Windows::Foundation::Metadata::WebHostHidden]
ref class ExpandableView : public Windows::UI::Xaml::DependencyObject
{
public:
static void onIsExpandedChanged(Windows::UI::Xaml::DependencyObject^ object,
Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ arguments);
public:
property bool IsExpanded
{
bool get(){return (bool)GetValue(IsExpandedProperty);}
void set(bool value){SetValue(IsExpandedProperty, value);}
}
static property Windows::UI::Xaml::DependencyProperty^ IsExpandedProperty
{
Windows::UI::Xaml::DependencyProperty^ get(){return _IsExpandedProperty;}
}
protected:
ExpandableView();
virtual void viewExpanded();
virtual void viewCollapsed();
private:
void _expand();
void _collapse();
private:
static Windows::UI::Xaml::DependencyProperty^ _IsExpandedProperty;
};
And I create a few User Controls which should be somehow inherited from this base class. And it is not possible to do it the way I want because winrt class can inherit only one ref class and other should be interfaces. But I need this very class which has dependency property which has some logic when it is set and I don't want to copy&past this property across all my classes.
So the question is: how to achieve it with WinRT?
Have you tried using a template and inheritance of the specific class needed:
template<typename BaseClass>
ref class ExpandableView : public BaseClass;
Now the subclasses reusing ExpandableView can inherit whatever they need, not only Windows::UI::Xaml::DependencyObject.
The application defines 3 interfaces to be implemented in a plug-in. Widget is always the base.
// Application code...
class Widget {
virtual void animate() = 0;
};
class BigWidget : public Widget {
};
class SmallWidget : public Widget {
};
Every interface implementation is derived from NiceWidget which provides some plug-in internal common information.
// Plug-in code...
class NiceWidget {
// nice::Thing is only known in plug-in code.
nice::Thing thing();
};
class NiceBigWidget : public NiceWidget, public BigWidget {
void animate() override;
};
class NiceSmallWidget : public NiceWidget, public SmallWidget {
void animate() override;
};
func is called from application code. wid is known to be implemented by this plugin. Thus wid is also a NiceWidget. The goal of func is to call the thing method of it.
// Plugin-in code...
void func(Widget* wid) {
// wid is either NiceBigWidget or NiceSmallWidget.
auto castedBig = dynamic_cast<NiceBigWidget*>(wid);
if (castedBig) {
castedBig->thing().foo();
return;
}
auto castedSmall = dynamic_cast<NiceSmallWidget*>(wid);
if (castedSmall) {
castedSmall->thing().foo();
return;
}
assert(false);
}
But trying to cast wid to every Nice* can become very awful with increasing hierarchy size. Are there better solutions out there?
First: if you know that wid will always be a NiceWidget*, why not say so in func()? And you would not need a cast at all:
void func(NiceWidget* wid)
{
wid->thing().foo(); // Done
}
Even if you can't change the function signature for whatever reason, you would only need one cast:
void func(Widget* wid)
{
NiceWidget* casted = dynamic_cast<NiceWidget*>(wid);
if (casted)
casted->thing().foo();
else
throw std::exception(); // Well, throw the right exception
}
You can assert() instead of throwing an exception, of course, if you think it is better for your purposes.
In any case, you just need a pointer to the class that defines the functions you need to use (in this case, thing()), not to the most derived classes. If you will override the function in derived classes, make it virtual and you are done anyway.
If you know, that every NiceWidget is Widget, you should consider extending NiceWidget from Widget.
class Widget {
virtual void animate() = 0;
};
class BigWidget : public Widget {
};
class SmallWidget : public Widget {
};
class NiceWidget : Widget{
// nice::Thing is only known in plug-in code.
nice::Thing thing();
};
class NiceBigWidget : public NiceWidget, public BigWidget {
void animate() override;
};
class NiceSmallWidget : public NiceWidget, public SmallWidget {
void animate() override;
};
There will be another problem called The diamond problem, and it may be solved using virtual extending
After that it's should be OK to dynamic_cast from Widget to NiceWidget