Private implementation for public interface method [duplicate] - c++

This question already has answers here:
Overriding public virtual functions with private functions in C++
(7 answers)
Closed 7 years ago.
I have encountered a piece of code with method being exposed via public interface while the implementation is private. I'm not sure what should be the expected behavior. Simplified example:
#include <iostream>
class Interface
{
public:
virtual ~Interface() {}
virtual void myIfMethod() = 0;
};
class Derived : public Interface
{
private:
void myIfMethod(){std::cout << "private method invoked via public interface" << std::endl;}
};
int main()
{
Interface* myObj = new Derived;
myObj->myIfMethod();
delete myObj;
return 0;
}
This sample compiles and executes without a warning: http://ideone.com/1Ouwk4
Is this a correct and well-defined behavior? And if so, why?
Note, the question isn't about private interface method with public implementation (there are multiple such questions on SO) but the other way around.

C++ standard draft
Access to virtual functions [class.access.virt]
1 The access rules (Clause 11) for a virtual function are determined by its declaration and are not affected by
the rules for a function that later overrides it.
2 Access is checked at the call point using the type of the expression used to denote the object for which the member function is called (B* in the example above). The access of the member function in the class in which it was defined (D in the example above) is in general not known.
The function is called through a pointer of type Interface in which the member function is public, so the access is allowed. The access of the derived member function is not known and has no effect. The behaviour is correct and well defined as far as the standard is concerned.
Of course, it might be quite pointless to define the overriding function private since it's accessible through virtual dispatch anyway.

Related

C++ Call child function from parent [duplicate]

This question already has answers here:
call to pure virtual function from base class constructor
(8 answers)
Calling virtual functions inside constructors
(15 answers)
Closed 1 year ago.
I am trying to call an overriden function from the parent, and found out that it just crashes.
This is quite hard to describe, so here the minimal reproducible code:
#include <iostream>
class A
{
public:
A()
{
init1();
}
void init1()
{
printf("1");
init2();
printf("2");
}
virtual void init2() = 0;
};
class B : public A
{
public:
B()
: A()
{}
void init2() override
{
printf("hello");
}
};
int main()
{
B b;
return 0;
}
On MSVC 2019 it crashes, on http://cpp.sh/ it outputs "1" and then main() returns 0, but we never see "hello" or "2".
Why does it crash? What happens from a low level point of view? Is A trying to call its own init2()?
Is there a way of doing it, so I don't have to, in every derived class, add init2() in its constructor?
You can't call a derived class's overriden methods from within a base class constructor (or destructor). The derived class portion of the object doesn't exist yet.
So, to answer your questions:
yes A::A() is trying to call A::init2(), not B::init2(), and thus crashes from calling a pure virtual method.
There are ways (like via CRTP) for a base class constructor to call a derived class method, but doing so has limitations to it (ie, not being able to access any derived class data members since they still don't exist yet, only base class data members can be accessed). In your example, B::init2() doesn't access anyB data members, so it is possible for A::A() to call B::init2(), but in general you really need to wait for B to begin/finish constructing itself before you can safely call B::init2().

C++ standard way to create "Abstract Class" (Pure Virtual Class) [duplicate]

This question already has answers here:
C++ abstract class without pure virtual functions?
(3 answers)
Closed 7 years ago.
I will start with what's most of us already know:
If I want my class to be abstract, I must define at least one of its methods as "pure virtual", for example, here, the method someFunction() is defined as "pure virtual", as it is defined with the virtual keyword and it is assigned with 0:
class SomeClass {
virtual void someFunction() = 0;
};
My question is, when I want an "abstract class", i.e. a class which cannot be instantiated (like "pure virtual" class), but I want to implement all its methods. Is there any standard way to do it?
My current workaround is ugly - I just define another dummy pure virtual method:
class UglyWorkaround {
public:
virtual void doAction1();
virtual void doAction2();
// My ugly workaround for making the class abstract - defining a dummy method
virtual void thisIsADummyMethod() = 0;
};
This is very bad, as any deriving non-abstract class will have to implement it
Is there a more standard/popular way to define and implement such a class?
I want to clarify - I don't want another ugly workaround - I ask whether there is any standard way that is commonly used. The objective is to make the code readable for other programmers, so they immediately understand that the class is abstract
Define the constructor protected

C++: why base object is not accessible inside derived class if protected [duplicate]

This question already has answers here:
Accessing protected members in a derived class
(8 answers)
Closed 9 years ago.
Am a newbie to C++.
class A
{
public:
int i;
protected: //**--- [1]**
void set()
{
i=5;
cout<<i;
}
};
class B : public A
{
public:
void call()
{
A obj;
obj.set(); //**----[2]**
set(); //**---[3]**
}
};
int main()
{
B* b_obj = new B;
b_obj->call();
}
Why doesn't the code compiled if i try including [2] and not replacing [1] to public BUT it works if i compile including [3] alone?
Compiled error: error: ‘void A::set()’ is protected.
In short, My intention is to understand why base object cannot be called in derived class if the access specifier for the base class interface is set as protected.
Not sure if my answer is correct, but here goes:
set is protected in class A. This means no outside member can access set, but derived classes can.
When calling set() by itself inside B you are calling the function as a derived function from A inside your derived class B, meaning the compiler will accept this because the function is protected (accessible to derived classes.)
However when you define A obj, calling obj.set(), in relation to the obj instance, the call is external to the class, hence why the compiler gives error.
Hope that helps.
Pet is unrelated to A or B, so whether f.set() is allowed depends on the definition of Pet. By contrast, just set() works because it's protected in the base class, and hence accessible in derived classes.

Calling pure virtual function in constructor gives an error [duplicate]

This question already has answers here:
call to pure virtual function from base class constructor
(8 answers)
Closed 5 years ago.
class a //my base class
{
public:
a()
{
foo();
}
virtual void foo() = 0;
};
class b : public a
{
public:
void foo()
{
}
};
int main()
{
b obj; //ERROR: undefined reference to a::foo()
}
Why it gives me error? The pure virtual foo is defined. What do I need to change in my code to make it work? I need pure virtual method from base class be called in its constructor.
Calling virtual functions in a constructor is recognised as a bad thing to do.
During base class construction of a derived class object, the type of
the object is that of the base class. Not only do virtual functions
resolve to the base class, but the parts of the language using runtime
type information (e.g., dynamic_cast (see Item 27) and typeid) treat
the object as a base class type.
So your instantiation of b invokes the a constructor. That calls foo(), but it's the foo() on a that gets called. And that (of course) is undefined.
Quoted from a book "Let Us C++"by Yashwant Kanetkar
It is always the member function of the current class , is called.That
is , the virtual mechanism doesn't work within the constructor
So, the foo() of class a gets called.
Since it is declared pure virtual, it will report an error
foo function is called in class a's constructor, and at that time, object b has not been fully constructed yet, hence it's foo implementation is unavailable.
Quoted from "Effective C++":
Don't call virtual functions during construction or destruction,
because such calls will never go to a more derived class than that of
the currently executing constructor or destructor

How to call overriden methods in all derived classes [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How to force child same virtual function call its parent virtual function first
I have a class hierarchy where each derived class overrides a given virtual function and starts its implementation by calling the one in its parent class. The goal is to have each of the derived implementation to be executed, but I do not like the way I do it.
For example, I have this class:
class base
{
public:
void do_stuff() { do_something(); }
virtual void do_something() { }
};
Then I derive this class on several levels:
class derived_10:
public derived_9 // which inherit from derived_8 and so on until derived_0
// which inherit from base
{
public:
virtual void do_something()
{
// this will also call derived_8::do_something() and so on
// until base::do_something()
derived_9::do_something();
// then, some stuff
}
};
I'm looking for a solution that will make sure that all derived_x::do_something() will be called in sequence when base::do_stuff() is called, without having to expect the derived classes to do this themselves. Do you have an idea of the best way to get this behavior ?
I've already asked a very similar question before: Calling overriden class methods as a chain in C++
The answer I've accepted pointed at your own solution. I can give you an idea about an alternative though. Constructors and destructors already have this behavior in C++, you might want to consider restructuring your code, so that the work is done during the construction or the destruction of an object that belongs to a class in a hierarchy. I'm not sure you'll be able to make this worth the effort though. On the other hand, you never know what you can get out of some template metaprogramming + some preprocessor magic.