I want to keep the actual struct hidden, but provide a interface name for user.
so my code goes:
class A
{
private:
struct B{...};
public:
using BPtr = B*;
B* funct(){...};
}
my usage would be
A a;
BPtr p = a.funct();
The full name is A::BPtr, so this will work:
A::BPtr p = a.funct();
On the other hand, this is pretty pointless, as only the name "B" is private – the class definition isn't.
For example,
class A
{
private:
struct B{ int x = 1234; } b;
public:
using BPtr = B*;
B* funct(){ return &b; };
};
int main() {
A a;
A::BPtr b = a.funct();
std::cout << b->x << std::endl;
}
outputs "1234", and so does
class A
{
private:
struct B{ int x = 1234; } b;
public:
B funct(){ return b; };
};
int main() {
A a;
std::cout << a.funct().x << std::endl;
}
even though A::B b = a.funct(); would not compile (but auto b = a.funct() would).
Lesson: if you hand someone a thing, they can use it - even if they don't know what to call it.
An addition to the answer by #molbdnilo:
Note that even if you don't expose the struct pointer as BPtr, it's not private anymore once you're returning it outside the class.
Here is an example of using the struct outside of the class:
#include <iostream>
#include <type_traits>
class A
{
private:
struct B { int num; };
public:
B* funct() { return new B {}; }
};
int main()
{
A a;
typedef std::remove_reference_t<decltype(*a.funct())> B;
B b { 3 };
std::cout << b.num << std::endl;
}
Related
Suppose there is a class A which has two subclasses, Aa and Ab. I want to make an array that can store pointers to objects of class Aa and Ab. If an array is declared with the type of class A, is this valid? If not, how can I accomplish this? For example:
A *arr;
//space allocated
Ab *obj1;
arr[x] = obj1;
On a related note, I want to write a function that when given a location, will return the object stored at that location in the array. If the above works and I have an array of objects of either Aa or Ab, the function could return an object of either type Aa or Ab. If the return type of the function is specified as A, the superclass, is this valid? If not, I have looked at template functions but cannot find a straight answer about just having the return type be variable, not the parameters. For this example, the function's parameter is always going to be int, but it could return an Aa or an Ab, depending on what is at that location in the array.
Yes that is the way polymorohism is achieved (using pointer to base class) and virtual methods.
Here is an example:
#include <iostream>
using namespace std;
#include <vector>
class A{
public:
virtual void foo()const{
std::cout << "A::foo()" << std::endl;
}
};
class Aa : public A {
public:
virtual void foo()const{
std::cout << "Aa::foo()" << std::endl;
}
};
class Ab : public A {
public:
virtual void foo()const{
std::cout << "Ab::foo()" << std::endl;
}
};
int main(){
A* ptrA[3];
A* a = new A;
Aa* aa = new Aa;
Ab* ab = new Ab;
ptrA[0] = aa;
ptrA[1] = ab;
ptrA[2] = a;
for(int i(0); i != 3; ++i)
ptrA[i]->foo();
delete a;
delete aa;
delete ab;
return 0;
}
Remember that C++ is Invariant not Contravariant which means you cannot assign a derived object a base object:
A* a = new A;
Ab* ab = a; // error
Is valid to have an array of base pointers, also you can use dynamic_cast to know in run time the return type of your array and use the API from the derived class. See and example below.
struct Base { virtual void do_something() {} };
struct Derived1 : Base
{
void first() const { std::cout << "first" << std::endl; }
void do_something() override {}
};
struct Derived2 : Base
{
void second() const { std::cout << "second" << std::endl; }
void do_something() override {}
};
Base& get(int option)
{
static std::vector<Base*> b {new Derived1{}, new Derived2{}};
return !option ? *b[0] : *b[1];
}
int main()
{
const int option {0};
// const int option {1};
if (Derived1* derived {dynamic_cast<Derived1*>(&get(option))})
{
derived->first();
}
else if (Derived2* derived {dynamic_cast<Derived2*>(&get(option))})
{
derived->second();
}
}
This is regarding the question
A class name introduced inside a class is not treated as a nested class name.
I am confused why Part1 and Part2 are different with respect to §3.3.2 [basic.scope.pdecl]/p7 of the standard:
Both are Elaborated Type specifiers and should fall into same section But it seems that there scope seems to be different
Part 1:
struct A
{
struct B;
B* m_b;
};
Part 2:
struct A
{
struct B* m_b;
};
Please guide me in this.
Maybe this little example will help to elaborate:
#include <iostream>
struct B {
void call() { std::cout << "B" << std::endl; }
};
struct A {
struct B* p;
};
struct A2 {
struct B;
struct B* p;
};
struct A2::B {
void call() { std::cout << "A2::B" << std::endl; }
};
int main()
{
B pb;
A2::B pb2;
auto a = A { &pb };
a.p->call();
auto a2 = A2 { &pb2 };
a2.p->call();
return 0;
}
expected results:
B
A2::B
Summary:
A::p is a B*
A2::p is a A2::B*
A2::B and B are entirely different classes
I'm trying to find my way around. I have two classes, A and B, where B inherits from A.
There are also two overloaded functions for A and B, that act on them in two different ways.
Now call these functions from a class function like this:
#include <iostream>
struct A;
struct B;
void f(A a);
void f(B b);
struct A {
int i;
A(): i(0) {};
void thisf() { f(*this); }
};
struct B: public A {
int j;
B(): j(1) {};
void thisf() { f(*this); }
};
void f(A a) { std::cout << a.i << std::endl; }
void f(B b) { std::cout << b.i << " " << b.j << std::endl; }
int main() {
A a;
B b;
a.thisf();
b.thisf();
return 0;
}
My question is: since A::thisf() and B::thisf() are the same (and will stay the same for more subclasses), is there a way how I can omit B::thisf() while still having the same functionality?
The expected output should look like:
0
0 1
More detail why I try to do this: I want to provide some custom render functionality to different kinds of data without bloating the class with render logic and have a separate render class with some state variables. But I don't want to give up the possibility to write
b.render()
in some situations. In my class definitions I want to spare every line I can.
I got the idea in this thread: https://gamedev.stackexchange.com/questions/63912/visitor-pattern-vs-inheritance-for-rendering
In your proposed problem you claim the need for a method in A and B that is not polymorphic and yet exhibits different behaviour in the two classes (linked by inheritance) with the same signature.
In addition, the method defers to a free function found by ADL (good!).
So... my question to you is this. If you already have the guarantee of a free function called f(A|B), why not simply document that as the interface?
If you insist on having thisf() you are causing yourself a problem because the inheritance relationship will cause B's thisf() to be ambiguous with A's. This can be solved with polymorphism (as per the other answer) but since you're rejecting that, you are are left with few options other than to eliminate the logically redundant thisf() altogether.
in any case, this code will do exactly as you want:
#include <iostream>
struct A;
struct B;
void f(A a);
void f(B b);
struct common_interface {
virtual void thisf() = 0;
};
template<class Host, class Base>
struct common_interface_impl : Base {
virtual void thisf() {
f(static_cast<Host&>(*this));
}
};
struct A : common_interface_impl<A, common_interface>
{
int i;
A(): i(0) {};
};
struct B: common_interface_impl <B, A>
{
int j;
B(): j(1) {};
};
void f(A a) { std::cout << a.i << std::endl; }
void f(B b) { std::cout << b.i << " " << b.j << std::endl; }
int main() {
A a;
B b;
a.thisf();
b.thisf();
return 0;
}
#include <iostream>
struct A {
int i;
A(): i(0) {};
virtual ~A() {};
virtual void thisf() { std::cout << i << std::endl; }
};
struct B: public A {
int j;
B(): j(1) {};
void thisf() { A::thisf(); std::cout << j << std::endl; }
};
void f( A* a )
{
a->thisf();
}
int main() {
A* a = new A();
A* b = new B();
f( a ); f( b );
delete a; delete b;
return 0;
}
I was wondering if it's possible to override just one function in a class without creating an entirely new class.
I would like bObj1.foo(); to output "foo!" and bObj2.foo() to output "foo?", but currently they both output "foo!".
#include <iostream>
using namespace std;
class B {
public:
virtual void foo() { cout << "foo!" << endl; }
};
class A {
public:
B f();
};
B A::f() {
B bObj;
return bObj;
}
class C : public A {
};
int main()
{
A aObj;
B bObj1 = aObj.f();
bObj1.foo(); // "foo!"
C cObj;
B bObj2 = cObj.f();
bObj2.foo(); // "foo?"
}
You can get the behavior that you want with a simple change, which consists in moving the "virtual" behavior to the A and C classes.
Here I modified your application to return the expected result:
#include <iostream>
using namespace std;
class A;
class B {
public:
B(A& a) : aref(a) {}
void foo();
private:
A& aref;
};
class A {
public:
B f();
virtual void foo() { cout << "foo!" << endl; }
};
B A::f() {
B bObj(*this);
return bObj;
}
class C : public A {
public:
virtual void foo() { cout << "foo?" << endl; }
};
void B::foo() { aref.foo(); }
int main()
{
A aObj;
B bObj1 = aObj.f();
bObj1.foo(); // "foo!"
C cObj;
B bObj2 = cObj.f();
bObj2.foo(); // "foo?"
}
In order to change the virtual function, you have to create a new type - there's no way around that in C++. However, an alternate mechanism - function objects - may do what you want here.
#include <functional>
#include <iostream>
using namespace std;
class B {
public:
B(function<void ()> foo_impl) : foo_impl(foo_impl) {}
void foo() {foo_impl();}
private:
function<void()> foo_impl;
};
class A {
public:
virtual B f();
};
B A::f() {
B bObj([](){cout << "foo!" << endl;});
return bObj;
}
class C : public A {
public:
virtual B f() override;
};
B C::f() {
B bObj([](){cout << "foo?" << endl;});
return bObj;
}
int main()
{
A aObj;
B bObj1 = aObj.f();
bObj1.foo(); // "foo!"
C cObj;
B bObj2 = cObj.f();
bObj2.foo(); // "foo?"
}
Assume the following simple case (notice the location of virtual)
class A {
virtual void func();
};
class B : public A {
void func();
};
class C : public B {
void func();
};
Would the following call call B::func() or C::func()?
B* ptr_b = new C();
ptr_b->func();
Your code is invalid C++. What are the parentheses in class definition?
It depends on the dynamic type of the object that is pointed to by pointer_to_b_type.
If I understand what you really want to ask, then 'Yes'. This calls C::func:
C c;
B* p = &c;
p->func();
Examples using pointers as well as reference.
Using pointer
B *pB = new C();
pB->func(); //calls C::func()
A *pA = new C();
pA->func(); //calls C::func()
Using reference. Note the last call: the most important call.
C c;
B & b = c;
b.func(); //calls C::func()
//IMPORTANT - using reference!
A & a = b;
a.func(); //calls C::func(), not B::func()
Online Demo : http://ideone.com/fdpU7
It calls the function in the class that you're referring to. It works it's way up if it doesn't exist, however.
Try the following code:
#include <iostream>
using namespace std;
class A {
public:
virtual void func() { cout << "Hi from A!" << endl; }
};
class B : public A {
public:
void func() { cout << "Hi from B!" << endl; }
};
class C : public B {
public:
void func() { cout << "Hi from C!" << endl; }
};
int main() {
B* b_object = new C;
b_object->func();
return 0;
}
Hope this helps