I want to make all functions in my base class invisible to my client, only accessible through my derived class.
Is there a way to do this in C++?
Thanks!
There are two ways one is
Using Protected Keyword
class A{
protected:
void f(){
std::cout << "F" << std::endl;s
}
};
class B:public A{
// access f() here...
};
Any derived class can access f() function from A class.
Second way:
Making B class friend class of A.
#include <iostream>
class A{
private:
void f(){
std::cout << "F" << std::endl;
}
friend class B;
};
class B:public A{
A obj;
public:
void accessF(){
obj.f();
}
};
int main(){
B obj;
obj.accessF();
return 0;
}
Use access-specifier (if base class is not under your control):
class A
{ public:
void f() {}
void h() {}
};
class B: private A // all members of A are private
{ public:
void g()
{ f();
}
using A::h; // adjust access
};
int main()
{ A a;
a.f();
B b;
b.g();
b.h();
b.f(); // error: 'void A::f()' is inaccessible
}
Related
I would like to hide a virtual method instead of override. I know for historic / compatibility reasons the override specifier is optional and overriding happens implicitly.
To stop overriding I usually adjusted the signature by adding a defaulted "Dummy" parameter. Is there a better way?
Assume this code:
#include <iostream>
class A{
public:
virtual void Foo()
{
std::cout << "A::Foo";
}
};
class B : public A
{
public:
void Foo() /*not override, just hide*/
{
std::cout << "B::Foo";
}
};
int main()
{
B b{};
A& a = b;
a.Foo(); //should print A::Foo - but prints B::Foo
}
What I did so far is this:
#include <iostream>
class A{
public:
virtual void Foo()
{
std::cout << "A::Foo";
}
};
template<typename T>
class reintroduce{};
class B : public A
{
public:
void Foo(reintroduce<B> = {}) /*not override, just hide*/
{
std::cout << "B::Foo";
}
};
int main()
{
B b{};
A& a = b;
a.Foo(); //should print A::Foo
}
The question is not too clear on the requirements of "hiding" but the following effectively "hides" the inherited method in the derived class, while not changing its visibility/accessibility in the base class.
#include <iostream>
class A {
public:
virtual void Foo()
{ std::cout << "A::Foo"; }
};
class B : public A
{
private:
using A::Foo;
};
int main()
{
B b;
b.Foo(); // error, cannot access private member
b.A::Foo(); // ok, calls A::Foo
A& a = b;
a.Foo(); // ok, calls A::Foo
}
For my C++ program I have a lot of classes where a member should be of one of two types which have the same base class.
I thought I could implement this with pointers but I don't get it to work.
Example: lets assume we have a class A with a member b_ of class B:
class A{
public:
A(B b): b_{b} {}
private:
B b_;
}
The class B has only one function which is pure virtual:
class B{
public:
virtual void print() = 0;
}
now I have two derived classes of B and I want to change A in a way, that it could hold eihther objects of class B1 or B2:
class B1: public B{
public:
void print(){cout << "B1\n";}
}
class B2: public B{
public:
void print(){cout << "B2\n";}
}
My plan was to use unique pointers:
class A{
public:
A(std::unique_ptr<B> b): b_{std::move(b)} {}
private:
std::unique_ptr<B> b_;
}
int main(){
std::unique_ptr<B> b;
if (some condition){
b = make_unique<B1>(new B1()) ///?
}else{
b = make_unique<B2>(new B2()) ///?
}
A(b);
A.getB()->print();
}
There are several mistakes on your code. First of, you can't have two definitions of A. Second, you must pass the unique_ptr as r-value reference (std::move) since it is not copyable. Last, make a variable of type A (a) and then call methods on it.
#include <memory>
#include <iostream>
using namespace std;
class B{
public:
virtual void print() = 0;
virtual ~B() {};
};
class B1: public B{
public:
void print(){cout << "B1\n";}
};
class B2: public B{
public:
void print(){cout << "B2\n";}
};
class A{
public:
A(std::unique_ptr<B> b): b_{std::move(b)} {}
auto *getB() { return b_.get(); }
private:
std::unique_ptr<B> b_;
};
int main()
{
std::unique_ptr<B> b;
if(false)
b = make_unique<B1>();
else
b = make_unique<B2>();
A a(std::move(b));
a.getB()->print();
}
I have two base classes and a class that inherits both base classes.
Both base classes have a virtual function with the same signature, and I want to provide different implementations in the derived class to each virtual function.
class A{
virtual void f() = 0;
}
class B{
virtual void f() = 0;
}
class Derived:public A, public B{
void A::f() override{ // Error
...
}
void B::f() override{ // Error
...
}
}
What is the correct way to do this? (I cannot rename the virtual function. Actually the two base classes are generated from the same template class.)
template <typename T>
class AShim : public A {
void f() override {
static_cast<T*>(this)->A_f();
}
};
template <typename T>
class BShim : public B {
void f() override {
static_cast<T*>(this)->B_f();
}
};
class Derived: public AShim<Derived>, public BShim<Derived> {
void A_f();
void B_f();
};
class A {
public:
virtual void f() = 0;
};
class B {
public:
virtual void f() = 0;
};
class Derived :public A, public B {
public:
void A::f() {
cout << "Inside A's version"<<endl;
}
void B::f() {
cout << "Inside B's version"<<endl;
}
};
int main()
{
Derived derived;
cout << "calling A" << endl;
A *a;
a = &derived;
a->f();
cout << "calling B" << endl;
B *b;
b = &derived;
b->f();
}
Works fine for me. No need to explicitly mention override keyword as pure virtual functions will be overridden by virtue of its default properties.Use base class's scope while defining the functions as you have already done. Use public access specifier to enable derived classes to override the pure virtual function. That's all.
I wonder if it is possible to declare a pure virtual function in class AbstractBase and make a Base classes member visible in Derived so it will use the member of Base and not look for a implementation in Derived. So far, i tried making Base's member visual by trying to use using but it won't compile since the look up, in this case, seems to ignore using. Is this possible at all? Here is my code:
#include <iostream>
using namespace std;
class AbstractBase {
public:
AbstractBase(){}
virtual ~AbstractBase(){}
protected:
virtual void f() = 0;
};
class Base {
public:
Base(){}
protected:
void f() {cout << "called Base's f()" << endl;}
};
class Derived : public Base, public AbstractBase {
public:
Derived(){}
//using Base::f; /*this won't compile*/
private:
void f(){} /*Access Base's f() here rather than implement*/
};
int main()
{
Derived d;
}
Use :: operator:
class Derived : public Base {
public:
Derived(){}
private:
void f(){ Base::f() }
};
Also, you don't need to inherit from AbstractBase.
It looks to me that you would like f() to be pure-virtual but provide default implementation. In this case, it can be achieved this way:
#include <iostream>
using namespace std;
struct AbstractBaseWithDefaultF
{
virtual ~AbstractBaseWithDefaultF() = default;
virtual void f() = 0;
};
void AbstractBaseWithDefaultF::f()
{
cout << "called AbstractBaseWithDefaultF's f()" << endl;
}
struct Derived : AbstractBaseWithDefaultF
{
void f() override
{
AbstractBaseWithDefaultF::f();
cout << "called Derived's f()" << endl;
}
};
int main()
{
Derived d;
d.f();
}
Output:
called AbstractBaseWithDefaultF's f()
called Derived's f()
Here's a live Wandbox example.
I have the following code:
#include <iostream>
class A {
private:
int a;
public:
void setA(int a_);
friend int B::getA();
};
class B : public A {
public:
int getA();
};
void A::setA(int a_) {
a = a_;
}
int B::getA() {
return a;
}
int main() {
B myB;
myB.setA(9);
std::cout << myB.getA()<< std::endl;
return 0;
}
Compiling with g++ yields:
friend.cpp:10:16: error: use of undeclared identifier 'B'
friend int B::getA();
My thinking is that when the compiler is going through the class A definition, it does not yet know about class B. Therefore, I can forward declare B to take care of this problem:
#include <iostream>
class B;
class A {
...
That doesn't quite work:
friend.cpp:10:16: error: incomplete type 'B' named in nested name specifier
friend int B::getA();
It looks like the compiler isn't able to resolve the function as it is given.
How can I make a derived class function a friend in the base class?
Your code seems to violate the basic concept of data encapsulation. To resolve it, either make A::a protected, as #rici suggested, or define a getter in class A.
class A {
private:
int a;
public:
void setA(int a_);
virtual int getA();
};
class B : public A {
public:
int getA();
};
void A::setA(int a_) {
a = a_;
}
int A::getA() {
return a;
}
int B::getA() {
return A::getA();
}