The question extends this question
The situation is the following. I'm extending a virtual method of a inner class:
class ClassOne {
public:
class InnerClass {
public:
virtual void method1();
protected:
friend class ClassOne
};
protected:
oftenUsedMethod();
private:
friend class InnerClass;
};
void ClassOne::InnerClass::method1()
{
#Do stuff with oftenUsedMethod();
}
class SubClassOne : public ClassOne {
class DerivedInnerClass : InnerClass {
virtual void method1();
};
};
void SubClassOne::DerivedInnerClass::method1()
{
##I need the access to the oftenUsedMethod???
}
Here is an image to try to clarify the problem :)
InnerClass uses ofthenUsedMethod() in its methods, and has access to it. To be able to extend the methods, I need access to ofthenUsedMethod() in DerivedInnerClass. Can this be achieved?
There are two problems to overcome:
Inner classes, by default, are not associated with an instance of the outer class, sou you'll have to make this dependency explicit by giving it a pointer to the outer class. If you do this, you'll need to be careful that instances of the inner class don't outlive the object they are referring to.
The derived inner class is not derived from the outer class so it does not have access to its protected members. What you can do is add a protected function into InnerClass that calls the function. This function is a member of InnerClass and derived classes can call it. Dynamic binding will do the rest.
Here is the above in C++:
#include <iostream>
class ClassOne
{
protected:
virtual void
oftenUsedMethod()
{
std::clog << "ClassOne::oftenUsedMethod()" << std::endl;
}
class InnerClass
{
private:
/** Pointer to an instance of the outer class. */
ClassOne *const outer_;
public:
InnerClass(ClassOne *const outer) : outer_ {outer}
{
}
protected:
virtual void
method1()
{
std::clog << "ClassOne::InnerClass::method1()" << std::endl;
this->dispatch();
}
/**
* Simply calls the protected member of the outer class.
* Derived classes can therefore access it indirectly, too.
*
*/
void
dispatch()
{
// Be aware: If *this->outer_ has already been destructed
// (and there is no simple way for us to tell whether it has),
// calling a member function on it will cause disaster.
this->outer_->oftenUsedMethod();
}
};
};
class SubClassOne : public ClassOne
{
protected:
virtual void
oftenUsedMethod() override
{
std::clog << "SubClassOne::oftenUsedMethod()" << std::endl;
}
class DerivedInnerClass : public ClassOne::InnerClass
{
DerivedInnerClass(ClassOne *const outer) : InnerClass {outer}
{
}
protected:
virtual void
method1() override
{
std::clog << "SubClassOne::DerivedInnerClass::method1()" << std::endl;
this->dispatch();
}
};
};
The override is a C++11 feature, you don't need it but it makes your intention clear.
Related
For example, I have 2 classes (in reality, it's more, that's why I'm asking this question) with the same methods:
class class1{
public:
void init(){
//something
}
void dostuff(){
//something
}
//
};
class class2{
public:
void init(){
//something
}
void dostuff(){
//something
}
//
};
And now a third one in which I want to deal with the two classes in the same manner:
class upclass{
public:
upclass(class12* argclass){
myclass=argclass;
myclass->init();
}
void domorestuff(){
myclass->dostuff();
}
private:
class12* myclass; //pointer to class 1 OR class 2
};
My question is now, do I need multiple constructors and multiple declarations to make it work or is there a way around it? Is it even possible to make "class12" a spacekeeper for these types without preprocessor-directives?
I am sorry to say, this is a wide field and there are really many many possible solution.
But I guess that we are talking about object- oriented programming, derivation and plymorphic functions. What you describe, will be typically solved with a class hierachy.
You have one base class with virtual (polymorphic) functions.
Then you derive other classes from this base class and override the virtual functions from the base class.
In a 3rd step, you create some instances of the derived classes dynamically, during runtime and you store the newly created classes (their address) in a pointer to the base class.
Later, you can call any of the virtual overriden function through the base class pointer. And mechanism behind the scenes will call the correct function for you.
Additionally. You defined some function init. Such a function name suggests the usage of a class-constructor. This will be called automatically in the correct sequence. First the base class constructor and then the derived class constructor.
Please see the below example:
#include <iostream>
#include <string>
class Base {
std::string baseName{};
public:
Base() { // Do initialization stuff
baseName = "Base";
std::cout << "\nConstructor Base\n";
}
virtual void doStuff() { // virtual function
std::cout << baseName << '\n';
}
};
class Derived1 : public Base {
std::string derivedName{};
public:
Derived1() : Base() { // Do initialization stuff
derivedName = "Derived1";
std::cout << "Constructor Derived1\n";
}
void doStuff() override { // Override virtaul function
std::cout << derivedName << '\n';
}
};
class Derived2 : public Base {
std::string derivedName{};
public:
Derived2() : Base() { // Do initialization stuff
derivedName = "Derived2";
std::cout << "Constructor Derived2\n\n";
}
void doStuff() override { // Override virtaul function
std::cout << derivedName << '\n';
}
};
int main() {
Base* base = new Base();
Base* derived1 = new Derived1(); // Store in base class pointer
Base* derived2 = new Derived2(); // Store in base class pointer
base->doStuff();
derived1->doStuff(); // Magic of polymorphism
derived2->doStuff(); // Magic of polymorphism
}
The Base class pointer will accept all classes derived from Base.
Please note. In reality you ould not use raw pointers and also to the constructor differently. This is just fotr demo.
But, you need to read several books about it to get the complete understanding.
You can explicitly write "store one of these" via std::variant and obtain the actual type (when needed) through std::visit:
#include <variant>
using class12 = std::variant<class1*, class2*>;
class upclass {
public:
upclass(class12 argclass): myclass{argclass} {
visit([](auto classn) { classn->init(); }, myclass);
}
void domorestuff() {
visit([](auto classn) { classn->dostuff(); }, myclass);
}
private:
class12 myclass;
};
If those visits get too repetitive, you might consider writing a pretty API to hide them:
class prettyclass12: public std::variant<class1*, class2*> {
private: // both g++ and clang want variant_size<>, a quick hack:
auto& upcast() { return static_cast<std::variant<class1*, class2*>&>(*this); }
public:
using std::variant<class1*, class2*>::variant;
void init() { visit([](auto classn) { classn->init(); }, upcast()); }
void dostuff() { visit([](auto classn) { classn->dostuff(); }, upcast()); }
};
class prettyupclass {
public:
prettyupclass(prettyclass12 argclass): myclass{argclass} { myclass.init(); }
void domorestuff() { myclass.dostuff(); }
private:
prettyclass12 myclass;
};
I have a class hierarchy like this:
class Base
{
public:
void start() { init(); }
private:
virtual void init() = 0;
};
class Default : public Base
{
private:
virtual void init() override {/*default implementation*/};
};
class Special : public Default
{
private:
virtual void init() override final {/*specialized implementation*/};
}
Which works alright if I call start() on an object of type Special;
Now I have a case where in the implementation in the Special class I want to call the implementation of the Default class.
Normally that would work with Default::init();, but will fail here due to the Defaults declaration of this is private.
Obviously one solution is to change this from private to protected, but I'd like to ask if there is another way? Rather than allowing any child to call this function directly, I'd like to limit this to calls that are initiated via virtual functions already defined in the Base or Default class.
Is there some option or modifier that would allow member function calls to be only allowed from child classes if they are within (the same) overriding virtual member functions?
C++ doesn't provide means to achieve this directly, so you'd have to work around, e. g. in piece of code below.
Well, if you absolutely want to. I personally would rather just fall back to making the functions protected, document what they are intended for and when to be called, and then just trust the deriving classes to do the stuff right. That in the end keeps the interfaces cleaner and doesn't rely on a rather unusual (and perhaps ugly) pattern (actually passing this twice).
class Base
{
public:
virtual ~Base() { }
void start()
{
InitProxy p(*this);
init(p);
}
protected:
class InitProxy
{
public:
InitProxy(InitProxy const&) = delete;
void init()
{
m_base.Base::init(*this);
}
private:
friend class Base;
Base& m_base;
InitProxy(Base& base)
: m_base(base)
{ }
};
private:
virtual void init(InitProxy& proxy) { }
};
class Derived : public Base
{
void init(InitProxy& proxy) override
{
proxy.init();
}
};
You could let the proxy accept a member function pointer, if you want to apply this constraint to more than one function, so you wouldn't have to re-write the proxy for every function separately. Possibly you'd need to make a template from then, if function parameters differ.
Forward declare Special, and make it a friend of Default:
class Base
{
public:
void start() { init(); }
private:
virtual void init() = 0;
};
class Special; // Forward declaration
class Default : public Base
{
private:
virtual void init() override {/*default implementation*/}
friend class Special; // Friend declaration
};
class Special : public Default
{
private:
virtual void init() override final {
Default::init();
/*Other implementation*/
}
};
Hi I am trying to implement an interface in C++. I want to be able to call a function from a class that could be implemented by various different classes. The approach I have tried fails since I cannot call the function with a pointer to the interface (abstract class). Here is the basic gist of the code I have tried:
Interface class:
class InterfaceClass{
virtual void handle() = 0;
};
Calling class:
CallingClass::CallingClass(InterfaceClass * owner){
this->owner = owner;
}
void CallingClass::doStuff(){
owner->handle();
}
Implementing classes:
class Class1 : public InterfaceClass {
public:
Class1();
void handle();
}
class Class2 : public InterfaceClass {
public:
Class2();
void handle();
}
each of the handle() functions in the implementing classes just prints out the class name. Each implementing class contains an object of the CallingClass which calls doStuff in a separate timer thread. I am trying to keep it so that the CallingClass doesnt need to know anything about the classes that implement the handle() function.
It fails since I cannot call the function of an abstract class. I expected this but cant figure a way around it. Any advise would be much appreciated! Let me know if any more information is needed.
Thanks
you were missing the public: keyword in the Interface class.
you need to remember that C++ class are by default private, so you should add public where it is needed.
this is a working example for you:
class InterfaceClass {
public:
virtual void handle() = 0;
};
class Calling{
public:
Calling(InterfaceClass * owner) {
this->owner = owner;
}
void doStuff() {
owner->handle();
}
~Calling() { delete owner; }
private :
InterfaceClass* owner;
};
class Class1 : public InterfaceClass {
public:
void handle() override
{
std::cout << "Class1"<<std::endl;
}
};
class Class2 : public InterfaceClass {
public:
void handle()
{
std::cout << "Class2" << std::endl;;
}
};
int main(int argc, char** argv)
{
Calling c1(new Class1());
c1.doStuff();
Calling c2(new Class2());
c2.doStuff();
}
I have encountered a virtual method in a nested class.
##classone.h
class ClassOne: {
public:
class InnerClass{
public:
virtual void method1();
...
##classone.cpp
void ClassOne::InnerClass::method1()
{
...
}
I am subclassing ClassOne and need to extend method1(). What need's to be done with the nested class in that situation?
What I tried
##subclassone.h
class SubClassOne: public ClassOne{
public:
virtual void method1();
##subclassone.cpp
void SubClassOne::InnerClass::method1()
{
##New implementation
}
But that gives a multiple definition of ClassOne::InnerClass::method1()
method1 belongs to ClassOne::InnerClass, not ClassOne. When you inherit from ClassOne, the nested class from base class becomes a member of the derived class, too, and you can reach it by qualifying with either ClassOne:: or SubClassOne::. Hence the double definition error regarding method1.
You'll need to sub-class InnerClass, too. If you still wish to derive from ClassOne, it would look like this:
class ClassOne {
public:
class InnerClass {
public:
virtual void method1();
};
};
void ClassOne::InnerClass::method1()
{
}
class SubClassOne : public ClassOne {
class DerivedInnerClass : InnerClass { //
virtual void method1();
};
};
void SubClassOne::DerivedInnerClass::method1()
{
}
My question might not be too correct... What I mean is:
class MyClass
{
public:
MyClass()
{
}
virtual void Event()
{
}
};
class FirstClass : public MyClass
{
string a; // I'm not even sure where to declare this...
public:
FirstClass()
{
}
virtual void Event()
{
a = "Hello"; // This is the variable that I wish to pass to the other class.
}
};
class SecondClass : public MyClass
{
public:
SecondClass()
{
}
virtual void Event()
{
if (a == "Hello")
cout << "This is what I wanted.";
}
};
I hope that this makes at least a little sense...
Edit: _This changed to a.
What you need to do is make SecondClass inherit from FirstClass and declare _This as protected.
class FirstClass : public MyClass
{
protected:
string _This;
public:
and
class SecondClass : public FirstClass
What you got doesn't make sense because classes can only see members and functions from their parents (MyClass in your case). Just because two class inherit from the same parent does not mean they have any relation or know anything about each other.
Also, protected means that all classes that inherit from this class will be able to see its members, but nobody else.
I guess that you need something like this (for a sake of simplicity, I've omitted all the unnecessary code):
class Base{
public:
~Base(){}
protected:
static int m_shared;
};
int Base::m_shared = -1;
class A : public Base{
public:
void Event(){
m_shared = 0;
}
};
class B : public Base{
public:
void Event(){
if (m_shared == 0) {
m_shared = 1;
}
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
B b;
a.Event();
b.Event();
return 0;
}
To explain above, I'll explain the static data members:
Non-static members are unique per class instance and you can't share them between class instances. On the other side, static members are shared by all instances of the class.
p.s. I suggest that you read this book (especially Observer pattern). Also note that above code is not thread-safe.