I know this question has been asked before in some form. But I am still confused.
Suppose I have two classes.
class A{
public:
void foo(int a, int b);
protected:
virtual void foo(int a) = 0;
}
class B : public class A{
void foo(int a);
}
Now if I want to make the visibility of the non virtual function in class A public in class B .... how do I do that?? ... In other words currently I am able to call the non virtual function in this manner
B b;
b.A::foo(3, 5);
and I want to avoid this ^
and the solution of putting this
using A::foo;
in public B refers the virtual function in A .... not the non-virtual function ... so I think that is not the solution.
class A{
public:
void foo(int a, int b);
protected:
virtual void foo(int a) = 0;
};
class B : public A{
public:
using A::foo;
protected:
void foo(int a);
};
void f()
{
B b;
b.foo(1,2); // OK
b.foo(3); // error: ‘virtual void B::foo(int)’ is protected within this context
}
works as expcted. foo with two parameters is callable, foo with one not.
Related
I have an abstract class A with the pure virtual method void foo(int a) = 0
Then I have several classes that inherit from A and all of them define the method foo. But I need one of them, B, to make it so foo takes an extra parameter, int b, so sort of an overload.
Then I would like to do this:
A *bInstance = new B();
bInstance -> foo(1, 2);
But I get an error telling me that foo is taking too many parameters.
Writing this, I realize it's kind of a weird thing to do so maybe you can't do this and it's good that you can't do it. But in case it is possible, please do tell me how I should go about it.
You can use the overloaded function of B only if the pointer to use is of type B.
See:
#include <iostream>
#include <memory>
class A{
public:
virtual void foo(int a) = 0;
};
class B : public A
{
public:
virtual void foo(int a) override
{
}
void foo(int a, int b)
{
std::cout << a << "," << b;
}
};
int main(){
auto b = std::make_shared<B>();
b->foo(1, 2);
//to use a:
A* aPtr = b.get();
aPtr->foo(1);
return 0;
}
Although Bernd's answer is a possiblility, you must ask yourself what the effect of an overload is. E.g., think of the following.
std::unique_ptr<A> bAsA = std::make_unique<B>();
bAsA->foo(1, 2); // no worky.
bAsA->foo(1); // works, but what should it do?
It there's a different interface between A and B, I would suggest to add a layer of abstraction in form of a new base class (which I will call C).
So instead of
struct A {
// common
virtual void bar() {}
// class specific
virtual void foo(int) = 0;
};
struct B: public A {
// weird unused override which is still available
void foo(int) override {}
// class specific
void foo(int, int) {}
};
use
struct C {
// common
virtual void bar() {}
};
struct A: public C {
// class specific
virtual void foo(int) = 0;
};
struct B: public C {
// class specific
void foo(int, int) {}
};
You can fully achieve want you want using a default parameter:
class A
{
public:
virtual void foo(int a, int b = 0) = 0;
virtual ~A() = default;
};
class B : public A
{
public:
void foo(int a, int b) override { }
};
class C : public A
{
public:
void foo(int a, int b = 0) override { }
};
int main()
{
A* b = new B();
A* c = new C();
b->foo(1, 2);
c->foo(1);
}
You don't have to use this parameter in C::foo implementation (and any other derived classes) if you don't need to.
I am just a beginner in C++, my question is can a virtual function access the friend of base class? or the virtual function will only access the class's friend function in which it is defined?
class A
{
friend class B;
public:
virtual void setData();
};
now if a class is derived from class A
class C:public class A{
public:
setData()
{
//can I use the friend class B here?
}
};
First, you have friendship backwards. B is a friend of A, but that gives A zero extra rights over B.
In C++, friendship does not commute. A says B is a friend, but A may not be a friend of B.
Second, friendship is not inherited. You don't go out drinking with your mother's friends.
Third, there are many ways to republish or share rights. The class that is a friend can have a method that does the operation on the friend.
Suppose you really wanted this:
class B {
friend class A;
void doStuff();
};
class A {
public:
virtual void setData(B* b) = 0;
};
class C:public A{
public:
virtual void setData(B* b) {
b->do_stuff();
}
};
C::setData generates an error. But we can change it like this:
class A {
protected:
void do_stuff_on_b(B* b) { b->do_stuff(); }
public:
virtual void setData(B* b) = 0;
};
class C:public A{
public:
virtual void setData(B* b) {
do_stuff_on_b(b);
}
};
we could also generalize this and create an access token:
class B {
struct access_token{ explicit access_token(int) {} };
friend class A;
public:
void doStuff(access_token);
};
class A {
protected:
static B::access_token access_b() { return access_token(0); };
public:
virtual void setData(B* b) = 0;
};
class C:public A{
public:
virtual void setData(B* b) {
b->do_stuff( access_b() );
}
};
where we gatekeep access to B private methods based on possession of an access token that can be passed around. The methods are public, but the token itself can only be created by friends.
Here is a skeleton code:
class C{
callMe(){}
};
class A{
// How to use callMe()
};
class B : C {
callMe();
A a;
};
In this example class B extends class C, so it can call callMe() method. But I need to use callMe() using class A given that class A can not extend class C. I wonder how?
you need to make A contain an object of type C.
class A
{
private:
C objC;
public:
void WhateverMethod() { objC.CallMe(); }
};
Also, the syntax for inheritance is
class B : C{
};
If you want B to simply have access to CallMe(), then you do not need to redefine it in B. It will inherit it from C. If you want B to override CallMe then you need to do this:
class C
{
public:
virtual void CallMe() { //definition }
};
class B : public C
{
public:
void CallMe() { //redefine it here }
};
Note, I assume from your syntax errors that you are a JAVA programmer. Methods are not automatically marked as virtual in C++, you have to mark them as virtual if you want to use polymorphism, and you have to use them from a pointer for it to work.
class C{
callMe(){}
friend class A;
};
class A{
//use call me here
};
You need to provide an instance of C:
class C {
public: // has to be public
void callMe() const {}
};
class A{
public:
A(const C& inst) : inst(inst) {}
void foo() {
inst.callMe();
}
private:
const C& inst;
};
Will a function pointer to a class member function which is declared virtual be valid?
class A {
public:
virtual void function(int param){ ... };
}
class B : public A {
virtual void function(int param){ ... };
}
//impl :
B b;
A* a = (A*)&b;
typedef void (A::*FP)(int param);
FP funcPtr = &A::function;
(a->*(funcPtr))(1234);
Will B::function be called?
Yes. Valid code to test on codepad or ideone :
class A {
public:
virtual void function(int param){
printf("A:function\n");
};
};
class B : public A {
public:
virtual void function(int param){
printf("B:function\n");
};
};
typedef void (A::*FP)(int param);
int main(void)
{
//impl :
B b;
A* a = (A*)&b;
FP funcPtr = &A::function;
(a->*(funcPtr))(1234);
}
Yes. It also works with virtual inheritance.
The function will be called, as you just try to invoke inherited function.
The best test for that thing is to make the methods in the class A a pure virtual method. In both cases (with or without pure virtual methods), B::function will be called.
i have something like this
class A {
virtual void doBla(A *a) = 0;
};
class B : public A {
virtual void doBla(B *b) { // do stuff ;};
};
and i want to do something like
A* a = new B();
B* b = new B();
a->doBla(b);
or: all children of A are supposed to have a method doBla which takes a parameter of the type of the child. Hope you get my problem and hope someone can help me or convince me that this is bad style :)
edit: added virtual to the methods
You cannot overload functions across base/child classes, and doBla member function of class A must be public if you want to call it from outside:
class A {
public:
virtual void doBla(A *a) = 0;
};
class B : public A {
virtual void doBla(A *a) { /*do stuff*/ }
};
Edit: Note that the declaration of doBla function is similar in A and B classes.
This is impossible as it stands - a doesn't have a doBla(B* b) function, so when you try to call it on the a instance the compiler can't guarantee in any way that function actually exists, and it doesn't know how to look it up. That's an error or ten.
What you might be looking for is double dispatch.
class A {
public:
virtual void doBla(A* a) { a->doBla_impl(this); }
private:
virtual void doBla_impl(A* a);
virtual void doBla_impl(B* b);
// etc
};
class B : public A {
public:
virtual void doBla(A* a) { a->doBla_impl(this); }
private:
virtual void doBla_impl(A* a);
virtual void doBla_impl(B* b);
// etc
};
The trouble with this is that you have to know all the derived types in the base class, which is not always possible or feasible.