I've written an abstract class (with pure virtual functions), and I'd like to have a method accept one such class as a parameter. Given that the class is abstract, I understand that I couldn't pass an abstract class to any method, but why can't I pass a subclass of an abstract class to that method? How do I specify that a parameter should be any of the subclasses of a specified baseclass? This is all in C++.
You need to specify the parameter as a pointer (or reference), e.g. Abstract * rather than Abstract. If Derived inherits from Abstract, you can pass a variable of type Derived * when Abstract * is expected, but you can't in general pass one of type Derived when Abstract is expected.
Then you use polymorphism in C++.
Given any base class:
struct Base{};
and its subclasses:
struct SubClassA : public Base(){};
struct SubClassB : public Base(){};
If you declare:
void MyFunctionReference(Base&){};
void MyFunctionPointer(Base*){};
You can then call:
{
SubClassA a;
SubClassB b;
MyFunctionReference(a); // by reference
MyFunctionPointer(&b); // by pointer address
}
You can indeed do this, observe:
Pure abstract class:
class Abstract {
public:
virtual void foo() = 0;
};
Child of overrides member function:
class AbstractImpl : public Abstract {
public:
void foo() override { std::cout << "Hi from subclass\n"; }
};
Now we declare a method that takes a reference type of the abstract class
void somefunc(Abstract &ab) {
ab.foo();
}
Finally in main we instantiate the child class parameter
int main() {
AbstractImpl test;
somefunc(test); // prints Hi from subclass
return 0;
}
Source: https://stackoverflow.com/a/11422101/2089675
Related
I want to understand the following c++ concept. class_a is abstract class and as per abstract class concept we cannot create any instance of it.
i have used the initlization list and abstract class as well but never used following concept.
In the code ,the initlization list of class_b, class_a is initlized. I want to understand what is meaning of initlizing it in the initilization list.
class_b::class_b(int val):nameA::class_a()
in fileA.cpp
namespace nameA
{
class class_a
{
public:
virtual ~class_a(){};
virtual void process()=0;
};
}
in fileb.h file
namespace nameB
{
class class_b : public nameA::class_a
{
public:
class_b(int val);
}
}
in fileb.cpp file
namespace nameB
{
class_b::class_b(int val)
:nameA::class_a() //Want to understand this line...
}
It would be more clear with a slightly richer example. Because if the abstract base class has neither attributes nor methods it is harder to see how it can be initialized.
class NamedProcessor {
std::string name; // a private attribute
public:
NamedProcessor(const std::string &name) : name(name) {}
virtual ~NamedProcessor() {}
// a pure virtual method to make the class abstract
virtual void process() = 0;
std::string getName() {
return name;
}
};
class Doubler : public NamedProcessor {
int value; // a private attribute
public:
Doubler(int initial = 1) : NamedProcessor("Doubler") {
reset(initial);
}
void reset(int initial) {
value = initial;
}
int getValue() {
return value;
}
// the concrete implementation
void process() {
value *= 2;
}
};
int main() {
// Compiler would croak witherror : variable type 'NamedProcessor' is an abstract class
// NamedProcessor wrong("Ill formed");
Doubler doubler;
std::cout << doubler.getName() << "\n"; // name has been initialized...
return 0;
}
Here the abstract class holds an attribute which will be available to subclasses. And this attribute has to be set at construction time because there is no public setter for it. The language has to provide a way to initialize the abstract subclass, meaning not building an object, but initializing a sub-object - here setting the name.
By deriving, every class_b object will contain a class_a sub-object.
Even if you cannot instanciate an object of type class_a, there may be a need of initializing this sub-object. Consider that an abstract class can also have members.
If you have an abstract class in terms of an interface (like in Java), this abstract class obviously needs no initialization. Nevertheless it would get a (empty) default constructor in C++, that you can call explicitly in the initialization list. (If you do not call it explicitly, it will be called implicitly.)
If class is abstract it doesn't mean that it can't have any constructor. It means that you can't use it for creating an independent object.
So here is classic inheritance mechanism:
You creating a child_class object
It calls a child_class() constructor
child_class() constructor calls base_class() constructor to guarantee that fields of base_class are built correct
Then executes child_class() constructor for the rest child_class fields
In your example you call class_a() constructor by yourself, but it will be called anyway. So in sum, it's not about abstract class, it's all about simple inheritance.
You need to have some mechanism for initializing class_a fields if they exists, that's why you can call class_a() constructor even if it's abstract class, otherwise inheritance mechanism just useless.
I have a base class with an implemented function and a pure virtual function which share a name, but not arguments. I can't call the function implemented in the base class from an instance of the derived class.
I've tried adding the function to the derived class instead of the base class and it works, but that would mean I have to add the function to every derived class instead of implementing it once in the base class.
I've also tried changing the functions name and it works. It seems to be due to a collision between the two overloaded functions.
template <typename T>
class Base {
public:
virtual T some_function(int x) = 0;
T some_function() {
// some code
}
}
class Derived final: public Base<int> {
int some_function() {
// some code
}
}
int main() {
Derived var = Derived();
var.some_function(3);// Compilation error
}
The above code does not compile indicating that it doesn't find the function: some_function(int).
The name some_function in Derived hides the name some_function inherited from Base. You have to bring it back into scope with a using declaration:
class Derived final: public Base<int> {
public:
using Base<int>::some_function;
int some_function() {
// some code
}
}
How would I do so without making base method virtual?
class Base {
public:
bool foo() const;
}
class Derived : public Base{
public:
bool foo() const;
}
There is no any sense to call isEmpty of a derived class from isEmpty of the base class because the base class knows nothing about its derived classes. Take into account that the base class is single while there can be numerous derived classes. So of what derived class are you going to call function isEmpty?
There is sense to call isEmpty of the base class in a derived class. it can be done the following way
bool Derived::isEmpty() const
{
return Base::isEmpty();
}
You cannot. That's why there is a virtual keyword. If your class forbids use of this keyword, I'd rather not use it as a starting point to learn OOP.
If you really need this, you can store a null pointer to a function with the foo's signature in your base class instances, and use the base implementation until this pointer is null. Then you can change this pointer in your derived class and associate is with your derived implementation. Then your base class can call that function via the pointer.
Below is some schematic code for this:
class Base {
public:
bool foo() const {
if (NULL == internalFoo) {
// base implementation;
} else {
return internalFoo();
}
}
private:
bool (*internalFoo)() = NULL;
}
class Derived : public Base{
public:
bool foo() const;
}
Is there a way you can invoke a member function of a base class upon a class derived from it?
Class Bass{
public:
void func();
};
Class Derived: public Base{
public:
void func();
};
I have a practice midterm, and I suspect no, because how would the Base class know about the Derived, but I am not sure.
Is there a way you can invoke a member function of a base class upon a class derived from it?
Not sure exactly what you mean by this, but given your Base and Derived classes you can do the following. Just make sure you use a reference or pointer, not pass-by-value because of the slicing problem.
Call Base::func() from within Derived::func():
void Derived::func()
{
Base::func();
}
Call Base::func() explicitly on a Derived object:
Derived d;
d.Base::func();
I [...] am wondering if you could do something like Base::func(Derived d)
As others have pointed out, you can do this using a forward declaration:
// Tell the compiler "Derived" is a class name.
class Derived;
class Base
{
// Can use the class name since it has been declared.
void func(Derived& derived);
};
// Define the class named "Derived".
class Derived : public Base
{
// ...
};
// Use the derived class.
void Base::func(Derived& derived)
{
// For this bit to work, the definition of `Derived` must
// be visible at this point (like putting the class above
// or including your "Derived.h" from "Base.cpp").
derived.some_derived_method();
}
However, you won't be able to define the Base::func(Derived&) directly in the class definition since you need to finished defining Base and to define Derived first.
if I understand correctly, you need to call base function with derived parameter?
You can do it only using forward declaration and passing derived object by pointer or ref.
class Derived;
class Base{
public:
void func(Derived&);
};
You should be able to do something like this:
class Derived;
class Base {
public:
void func();
void func(Derived);
};
class Derived : public Base {
public:
void func();
};
void
Base::func(Derived D) {
}
It is okay to use incomplete types in the Base's member function declarations, but you must provide the complete type before their definition.
You can use forward declaration of Derived class:
class Derived;
First of all, do you mean methods on an object, or static class methods?
Secondly, the answer is: it depends what the object you're invoking the method call on is. This is the nature of polymorphism: if your object is of type 'Derived', then even if it has been cast to a 'Base' the method call will still invoke the Derived version of func.
Is that what you were asking?
I believe, a derived class can override only those functions which it inherited from the base class. Is my understanding correct.?
That is if base class has a public member function say, func, then the derived class can override the member function func.
But if the base class has a private member function say, foo, then the derived class cannot override the member function foo.
Am i right?
Edit
I have come up with a code sample after studying the answers given by SO members. I am mentioning the points which i studied as comments in the code. Hope i am right. Thanks
/* Points to ponder:
1. Irrespective of the access specifier, the member functions can be override in base class.
But we cannot directly access the overriden function. It has to be invoked using a public
member function of base class.
2. A base class pointer holding the derived class obj's address can access only those members which
the derived class inherited from the base class. */
#include <iostream>
using namespace std;
class base
{
private:
virtual void do_op()
{
cout << "This is do_op() in base which is pvt\n";
}
public:
void op()
{
do_op();
}
};
class derived: public base
{
public:
void do_op()
{
cout << "This is do_op() in derived class\n";
}
};
int main()
{
base *bptr;
derived d;
bptr = &d;
bptr->op(); /* Invoking the overriden do_op() of derived class through the public
function op() of base class */
//bptr->do_op(); /* Error. bptr trying to access a member function which derived class
did not inherit from base class */
return 0;
}
You can override functions regardless of access specifiers. That's also the heart of the non-virtual interface idiom. The only requirement is of course that they are virtual.
But if the base class has a private member function say, foo, then the derived class cannot override the member function foo.
In Java, you can't. In C++, you can.
You are correct in that to override a function in a derived class, it must inherit it from the base class (in addition, the base class function must be virtual). However you are wrong about your assumption that virtual functions are not inherited. For example, the following works well (and is actually a known idiom for precondition/postcondition checking):
class Base
{
public:
void operate_on(some thing);
private:
virtual void do_operate_on(some thing) = 0;
};
void Base::operate_on(some thing)
{
// check preconditions
do_operate_on(thing);
// check postconditions
}
class Derived: public Base
{
// this overrides Base::do_operate_on
void do_operate_on(some thing);
};
void Derived::do_operate_on(some thing)
{
// do something
}
int main()
{
some thing;
Base* p = new Derived;
// this calls Base::operate_on, which in turn calls the overridden
// Derived::do_operate_on, not Base::do_operate_on (which doesn't have an
// implementation anyway)
p->operate_on(thing);
delete p;
}
A way to see that private methods are really inherited is to look at the error messages generated by the following code:
class Base
{
private:
void private_method_of_B();
};
class Derived:
public Base
{
};
int main()
{
Derived d;
d.private_method_of_B();
d.method_that_does_not_exist();
}
Trying to compile this with g++ leads tot he following error messages:
privatemethodinheritance.cc: In function 'int main()':
privatemethodinheritance.cc:4: error: 'void Base::private_method_of_B()' is private
privatemethodinheritance.cc:15: error: within this context
privatemethodinheritance.cc:16: error: 'class Derived' has no member named 'method_that_does_not_exist'
If class Derived wouldn't inherit that function, the error message would be the same in both cases.
No You can not over ride any function in base class .
My reason for this notion is that if you define the function in derived class that has the same function signiture in base class , the base class function will become hidden for derived class .
For more information about this exciting issue just visit :
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Foverload_member_fn_base_derived.htm
It's also depends on the type of inheritance
class Derived : [public | protected | private] Base { };
In order to override a function inherited from base class, it should be both virtual, and classified as public or protected.