I have the following code:
class outer
{
struct inner
{
int var1;
int var2;
inner() { var1 = 1; var2 = 2; }
};
inner inner_instance;
public:
const inner *get_inner() { return &inner_instance; }
};
int main(int argc, char *argv[])
{
// 1
outer outer_instance;
cout << outer_instance.get_inner()->var1 << endl;
// 2
// this cannot be compiled because outer::inner is private
//const outer::inner *inner_ref = outer_instance.get_inner();
//cout << inner_ref->var1;
// 3
const int *inner_var2 = (int *) outer_instance.get_inner();
inner_var2++;
cout << *inner_var2 << endl;
return 0;
}
I understand why No.2 cannot be compiled. I just do not know what is the design idea of the compiler that allows access to the public fields of a private nested class but not the nested class itself, like No.1. The instance data is still in the memory. If I know the structure of such private nested class, I can still achieve assigning like No.3 does.
Does that mean it is better not to return pointer or reference of a private nested class in a public function? And if I really have to return something about the nested class to the outer world, make it public?
Thanks!
Put the struct inner definition in the public if you want to use it outside outer class.
class outer
{
public:
struct inner
{
int var1;
int var2;
inner() { var1 = 1; var2 = 2; }
};
private:
inner inner_instance;
public:
const inner *get_inner() { return &inner_instance; }
};
You are right, it is best if the types used in the public API are not private. They may be forward declared only, though (if you only use pointers or references on the API).
Related
I want to return a copy of struct from public class function, and i define this struct inside this class as a private member.
Is it possible to return this structure of any other type of custom data?
Consider this simple example:
class Test {
private:
struct sTest {
int i = 1;
}_sTest;
public:
sTest GetStruct() {
return _sTest;
}
};
then after i create object of this class:
Test cTest;
how can i call
cTest.GetStruct()
to get
_sTest
?
You can use auto to store the object.
Following is sample code. See it here in action:
#include <iostream>
using namespace std;
class Test {
private:
struct sTest {
int i = 1;
}_sTest;
public:
sTest GetStruct() {
return _sTest;
}
};
int main()
{
Test a;
auto obj = a.GetStruct();
cout<< obj.i <<"\nDone!!!\n";
return 0;
}
Output:
1
Done!!!
Note: It is fine on other compilers also. Check here on other compilers also.
Just in case you don't want to declare your struct within your class:
// not necessarily a member function
auto GetStruct()
{
struct sTest {
int i = 1;
};
return sTest();
}
using test_t = decltype(GetStruct()); // you can make an alias for an anonymous struct.
auto test = GetStruct();
Since the private class is not accessible from the class Test outside, use the keyword auto.
auto test = cTest.GetStruct();
Yes, it is perfectly safe. It is like any other type of data. With auto you are just telling the compiler to guess which kind of variable would be.
In this program, I am trying to inculcate hybrid inheritance in this program but this is giving wrong output. I have taken arithmetic as base class and add,sub,mul,div as its derived classes.
And then I have derived a class result using add,sub,mul,div as base classes. I have tried all the data types but with all it gives wrong or zero output.
#include "iostream"
using namespace std;
class arithmetic
{
public:
float var1,var2;
void introduce()
{
cout<<"This program will perform arithmetic on two variables"<<endl
<<"Enter the first variable: ";
cin>>var1;
cout<<"Enter the second variable: ";
cin>>var2;
}
};
class add:public arithmetic
{
protected:
float res_add;
public:
void show_add()
{
res_add=var1+var2;
cout<<"Addition of those variables gives "<<res_add<<endl;
}
};
class sub:public arithmetic
{
protected:
float res_sub;
public:
void show_sub()
{
res_sub=var1-var2;
cout<<"Subtraction of those variables gives "<<res_sub<<endl;
}
};
class mul:public arithmetic
{
protected:
float res_mul;
public:
void show_mul()
{
res_mul=var1*var2;
cout<<"Multiplication of those variables gives "<<res_mul<<endl;
}
};
class div:public arithmetic
{
protected:
float res_div;
public:
void show_div()
{
res_div=var1/var2;
cout<<"Divison of those variables gives "<<res_div<<endl;
}
};
class result:public add, public sub,public mul,public div
{
public:
void showres()
{
cout<<"Arithmetic on the given two varibales gives us the following result:"<<endl;
}
};
int main()
{
result example;
arithmetic var;
var.introduce();
example.showres();
example.show_add();
example.show_sub();
example.show_mul();
example.show_div();
return 0;
}
You are creating two separate object var (base class object) and example ( derived class object). Initializing the var1 and var2 by calling the var.introduce() and calling the methods show_add(), show_sub() etc. in the example object, in example object var1 and var2 is not initialized. so whatever arithmetic operation you are calling is getting applied in the uninitialized var1 and var2 member variable of example object.
you don't need to create the base class object(var). call the intruduce() method from the example then it will start working fine.
Please go through the below sample code to understand the concept of virtual base class.
#include <iostream>
class A
{
public:
int i;
};
class B : virtual public A
{
public:
int j;
};
class C: virtual public A
{
public:
int k;
};
class D: public B, public C
{
public:
int sum;
};
int main()
{
D ob;
ob.i = 10; //unambiguous since only one copy of i is inherited.
ob.j = 20;
ob.k = 30;
ob.sum = ob.i + ob.j + ob.k;
std::cout << "Value of i is : "<< ob.i<<"\n";
std::cout << "Value of j is : "<< ob.j<<"\n";
std::cout << "Value of k is : "<< ob.k<<"\n";
std::cout << "Sum is : "<< ob.sum <<"\n";
return 0;
}
Output:
Value of i is : 10
Value of j is : 20
Value of k is : 30
Sum is : 60
Live Demo on coliru
If you want to avoid virtual inheritance and want something simpler, use composition.
For this, class result should contain objects of add, sub, mul and div.
The resulting code for result will look something like this:
class result:public arithmetic
{
public:
mul m;
add a;
sub s;
div d;
void assignvals()
{
m.var1 = var1; m.var2 = var2;
a.var1 = var1; a.var2 = var2;
s.var1 = var1; s.var2 = var2;
d.var1 = var1; d.var2 = var2;
}
void showres()
{
cout<<"Arithmetic on the given two variables gives us the following result:"<<endl;
}
};
The resulting code for main will look something like this:
int main()
{
result example;
example.introduce();
example.assignvals();
example.showres();
example.a.show_add();
example.s.show_sub();
example.m.show_mul();
example.d.show_div();
return 0;
}
Note: Some compilers will complain if div is used as a class name because it is also the name of a library function in C++. So you will have to change the name of this class.
I need to catch cases in C++ code when there are two or more similar access specifiers in the class.
Let's say there are two classes
class A{
public:
int b;
public:
int a;
}
class B{
public:
int a;
}
How to match class A (because it has two 'public's) but not class B with ASTMatcher?
This matcher grabs the 'public' declaration:
accessSpecDecl(
isPublic(),
hasAncestor(cxxRecordDecl().bind("crd"))).bind("asd")
In the callback class, you can track the number of hits the matcher gets for a given struct declaration, for example with a std::map<string,int>:
struct report_public : public MatchCallback{
using map_t = std::map<string,int>;
using map_it = map_t::iterator;
map_t count;
void run(MatchResult const & result){
AccessSpecDecl const * asd = result.Nodes.getNodeAs<AccessSpecDecl>("asd");
CXXRecordDecl const * crd = result.Nodes.getNodeAs<CXXRecordDecl>("crd");
if(asd && crd){
string const struct_name = crd->getNameAsString();
map_it it = count.find(struct_name);
if(it != count.end()) count[struct_name]++;
else count[struct_name] = 1;
}
else { /* error handling */}
return;
} // run
}; // report_public
i was wondering if is possible make that a method of class points to another method of other class:
consider this:
// Class Foo:
class Foo
{
static int GetA(int a);
static int GetB(int b);
};
int Foo::GetA(int a)
{
return a * 2;
}
int Foo::GetB(int b)
{
return a * 4;
}
// Hooking class methods:
class HookFoo
{
static int HookGetA(int);
static int HookGetB(int);
};
int(HookFoo::*HookGetA)(int) = (int(HookFoo::*)(int))0x0; // (0x0 Memory address) or for example: &Foo::GetA;
int(HookFoo::*HookGetB)(int) = (int(HookFoo::*)(int))0x0; // (0x0 Memory address) or for example: &Foo::GetA;
I know it's possible do some like:
int(*NewHook)(int) = &Foo::GetA;
but how i can do for declare the methods into of a class?
Here is more or less what you tried to achieve (minimal, working example):
class Foo
{
public:
static int GetA(int a);
static int GetB(int b);
};
int Foo::GetA(int a)
{
return a * 2;
}
int Foo::GetB(int b)
{
return b * 4;
}
class HookFoo
{
public:
using FuncType = int(*)(int);
static FuncType HookGetA;
static FuncType HookGetB;
};
// Initialized with Foo::GetA
HookFoo::FuncType HookFoo::HookGetA = &Foo::GetA;
// nullptr'ed
HookFoo::FuncType HookFoo::HookGetB = nullptr;
int main() {
HookFoo::HookGetA(0);
}
For the methods in Foo are static, you can use a simple function pointer type to refer to them. You don't have to use (and can't use actually) a member function pointer in this case.
The using declaration helps to have a more readable code.
When you have correctly initialized your hooks, you can invoke them (thus the pointed functions) as you can see in the main.
I added a couple of visibility specifiers for your methods and data members were all private.
You can use function pointers.
Ex:
class A {
public:
static void say_hello() { cout << "Hello\n"; }
};
class B {
public:
static void(*hook)();
};
void(*B::hook)() = A::say_hello;
int main()
{
B::hook();
}
If you need to hook into functions at a specific address, use a function pointer. You can't reassign functions like that
// typedef your function pointers, it makes the syntax a lot easier
typedef int(*FHook)(int);
class HookFoo
{
static FHook HookGetA;
static FHook HookGetB;
};
// assign to address
FHook HookFoo::HookGetA = (FHook)0x1234;
FHook HookFoo::HookGetB = (FHook)0x5678;
Of course its your job to make sure the addresses are correct.
the explicit function pointer types would be as such:
class HookFoo
{
static int (*HookGetA)(int);
static int (*HookGetB)(int);
};
int (*HookFoo::HookGetA)(int) = (int(*)(int))0x1234;
int (*HookFoo::HookGetB)(int) = (int(*)(int))0x5678;
I need some help on a strange mix between function pointers and templates...
My target :
You have a class : template<typename B> class A, and A instanciate a B member. Now I want to acces B getter/setter.
I tried this :
class B_example
{
public:
B_example(int v):m_var(v){}
int getVar() { return m_var; }
void setVar(int v) { m_var = v; }
private:
int m_var;
};
template<typename B> class A
{
public:
A():m_b(B(5))
{
get = &m_b.getVar;
set = &m_b.setVar;
}
int (B::*get)();
void (B::*set)(int);
private:
B m_b;
};
int main(int argc, char** argv)
{
A<B_example> A_instance;
B_example B_instance(5);
int a = (A_instance.get*)();
std::cout << a << std::endl;
}
Thank's for any help.
Alexandre
First, fix the syntax errors:
get = &B::getVar;
set = &B::setVar;
Then, the member-function pointer needs to be called on an object. Without knowing the purpose of these strange pointers, I can't guess what you want to do here. Maybe you want to call on B_instance:
int a = (B_instance.*A_instance.get)();
Or maybe you want to call it on the m_b object within A_instance; but you can't do that because it's private. If that's the case, you probably just want regular member functions, rather than weird function pointers
int get() {return m_b.getVar();}
void set(int v) {m_b.setVar(v);}
These:
get = &m_b.getVar;
set = &m_b.setVar;
Should be:
get = &B::getVar;
set = &B::setVar;
And (A_instance.get*)() should be (B_instance.*A_instance.get)().