Pure virtual functions with arguments of the same class - c++

I'd appreciate if anyone could enlighten me what is going on here: Say I declare the following
class Base {
public:
virtual void member(Base b) = 0;
};
which give the following compiler error:
pvf.cpp:3:18: error: cannot declare parameter ‘b’ to be of abstract type ‘Base’
virtual void member(Base b) = 0;
^
pvf.cpp:1:7: note: because the following virtual functions are pure within ‘Base’:
class Base {
^
pvf.cpp:3:18: note: virtual void Base::member(Base)
virtual void member(Base b) = 0;
However, if I pass by reference, it compiles without problems:
class Base {
public:
virtual void member(Base& b) = 0;
};
Furthermore, I'd like to implement member() in the derived class as
class Base {
public:
virtual void member(Base& b) = 0;
};
class Derived : public Base {
public:
void member(Derived& d) {};
};
int main() {
Derived d;
}
However, (obviously?) I get
pvf.cpp: In function ‘int main()’:
pvf.cpp:12:14: error: cannot declare variable ‘d’ to be of abstract type ‘Derived’
Derived d;
^
pvf.cpp:6:8: note: because the following virtual functions are pure within ‘Derived’:
class Derived : public Base {
^
pvf.cpp:3:15: note: virtual void Base::member(Base&)
virtual void member(Base& b) = 0;

Your first function
virtual void member(Base b) = 0;
takes a parameter of class Base by value which requires an instance of Base to be passed to it. But as Base is an abstract class (because it contains a pure virtual function) it cannot be instantiated and therefore you cannot create an instance of Base to pass to it! That is the reason for your first error.
In your second case, in your derived class you declare a function
void member(Derived& d) {};
which you may think overrides the base class virtual function
virtual void member(Base& b) = 0;
but it does not (it in fact, hides it - see Why does a virtual function get hidden? for an explanation of this), and so Derived remains abstract class because you have not provided an implementation of the pure virtual function in the base class. For this reason Derived also cannot be instantiated. Derived classes that fail to provide an implementation for a base class pure virtual function will remain abstract just like the base class.

Related

Why can't I access the protected function in the derived class

I have a Base class and derived another class from it. The derived class has a function which takes as an argument const Base& and calls its protected member function. I get an error saying that the function being called is protected in that context. I'd like to know why that happens and can I solve it without making the protected function in base class public.
class Base {
protected:
void call() const {}
};
class C : public Base {
public:
void func(const Base& b) {
b.call();
}
};
I tried adding using Base::call in the derived class but that didn't help

Why do I get compile time error when base class pointer points to derived class virtual function that is declared in base class?

I have a base class which has virtual void function1( ) and that is overridden in derived class. Additionally there is one more virtual function in my derived class as below.
class Base
{
public:
virtual void function1()
{
cout<<"Base::Virtual function1"<<endl;
}
};
class Derived1:public Base
{
public:
void function1()
{
cout<<"Derived1::Function1"<<endl;
}
virtual void function2()
{
cout<<"Derived1::function2"<<endl;
}
};
int main()
{
Base *bptr = new Derived1();
Derived1 *dptr = new Derived2();
bptr->function2(); //compile time error
return 0;
}
I want to know what happens at compile time which is causing compile time error.
I want an answer in an interview point of view. How does Vtable and Vptr behave in this scenario. I know there will be one vptr for Base class and that will be inherited to Derived1 class. What does compiler check at compile time?
In the base class Base you dont have a virtual function2, so if you use "Base" as a type compiler can't find a function2.
Change to:
class Base
{
public:
virtual void function1()
{
cout<<"Base::Virtual function1"<<endl;
}
virtual void function2() = 0;
};
And you can use function2.
There is another error since you have no Derived2
The compiler does not keep track of the run time type of bptr, and instead always considers it to point to an instance of Base. You have to declare function2 in Base as well for the compiler to acknowledge it. Also, shouldn't function1 in Derived be declared virtual as in the base class?

virtual inheritance query

class Base {
public:
Base(){ }
virtual void Bfun1();
virtual void Bfun2();
};
class Derv : public Base {
public:
Derv(){ }
void Dfun1();
};
Is there a difference between above definitions and the below ones ? Are they same ? if not how both are the different functionally ?
class Base {
public:
Base(){ }
void Bfun1();
void Bfun2();
};
class Derv : public virtual Base {
public:
Derv(){ }
void Dfun1();
};
They are completely different. The first set defines Bfun1 and Bfun2 as virtual function, that allows overriding them in the derived class and call those in the derived class through a base class pointer:
// assume you've overridden the functions in Derived
Base* base_ptr = new Derived;
base_ptr->Bfun1(); // will call function in derived
The second set, however, they're just normal functions. Instead, you declared the base class to be virtual, which has many implications you best read about in a good C++ book or search through the SO questions, I think we have one on that topic.

A way to enforce use of interface in C++

In C++, let's say I have a class Derived that implements an interface class BaseInterface, where BaseInterface has only pure virtual functions and a virtual destructor:
class BaseInterface
{
public:
virtual void doSomething() = 0;
~BaseInterface(){}
};
class Derived : public BaseInterface
{
public:
Derived() {}
~Derived(){}
protected:
virtual void doSomething();
private:
int x;
};
No classes outside the Derived class hierarchy should call Derived::doSomething() directly, i.e., it should only be accessed polymorphically through the BaseInterface class. To enforce this rule, I have made Derived::doSomething() protected. This works well, but I'm looking for opinions pro/con regarding this approach.
Thanks!
Ken
I think you're looking for the non-virtual interface (NVI) pattern: a public non-virtual interface that calls a protected or private virtual implementation:
class BaseInterface
{
public:
virtual ~BaseInterface(){}
void doSomething() { doSomethingImpl(); }
protected:
virtual void doSomethingImpl() = 0;
};
class Derived : public BaseInterface
{
public:
Derived() {}
virtual ~Derived(){}
protected:
virtual void doSomethingImpl();
private:
int x;
};
If it is part of the interface, why would you not want users to call it? Note that as it is, they can call it: static_cast<BaseInterface&>(o).doSomething() is just an awkward way of saying o.doSomething(). What is the point of using the interface... if the object fulfills the interface, then you should be able to use it, or am I missing something?
Since you are not actually blocking anyone from calling the methods, I don't see a point in making the code more complex (both the class and users of the class) for no particular reason. Note that this is completely different from the Non-Virtual Interface in that in this idiom virtual functions are not accessible publicly (at any level) while in your case, the intention is allowing access, and making it cumbersome.
What you are doing is also mentioned in standard ISO/IEC 14882:2003(E) 11.6.1 and believe you are correct. Other than the fact, the member function isn't pure virtual in the given example. It should hold for pure virtual functions too, AFAIK.
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.
[Example:
class B
{
public:
virtual int f();
};
class D : public B
{
private:
int f();
};
void f()
{
D d;
B* pb = &d;
D* pd = &d;
pb->f(); // OK: B::f() is public,
// D::f() is invoked
pd->f(); // error: D::f() is private
}
—end example]
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 key is the rest of your code. Only accept a BaseInterface* as an argument to any methods that require the doSomething() call. The client programmer is forced to derive from the interface to make his code compile.
This makes no sense to me. Regardless of which pointer you call doSomething(), you would still wind up with the method defined in most derived class. Consider the following scenario:
class BaseInterface
{
public:
virtual void doSomething() = 0;
~BaseInterface(){}
};
class Derived : public BaseInterface
{
public:
Derived() {}
~Derived(){}
virtual void doSomething(){}
private:
int x;
};
class SecondDerived : public Derived
{
public:
SecondDerived() {}
~SecondDerived(){}
private:
int x;
};
int main(int argc, char* argv[])
{
SecondDerived derived;
derived.doSomething(); //Derived::doSomething is called
BaseInterface* pInt = &derived;
pInt->doSomething(); //Derived::doSomething is called
return 0;
}

C++ error: cannot declare field to be of abstract type

This is the situation:
class Base {
virtual void methodA() = 0;
virtual void methodB() = 0;
};
class Base_A : public Base {
void methodA();
void methodB();
};
class Base_B : public Base {
void methodA();
void methodB();
};
class MyClass {
private:
Base * b;
};
When I compile it gives the error message:
error: cannot declare field MyClass::b to be of abstract type because the following virtual functions are pure within Base:
Base::methodA()
Base::methodB()
How to solve this?
UPDATE
It compiles now. I dont'know what I have changed
You code seems correct and perfect .
Your Base Class is Abstract so you can't create object of it ,
but you can definately declare pointer of it.
So you might have written Base b instead of Base *b ,please check it.
Your code snippets compiles fine on my computer. Are you sure that you are using Base* b, ie. a pointer type and not Base b?