could I create an empty class with a specific size? - c++

I made an empty class having specific offset and want to derived class using that area..
like below code.. I use alignas()
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
#pragma pack (push, 1)
class alignas(32) base
{
public:
base() { init(); }
void init() { memset(this, 0, 32); }
}; // sizeof(base) = 32
class derived01 : public base
{
int a;
int b;
}; // sizeof(derived01) = 32
class derived02 : public base
{
char a[20];
}; // sizeof(derived02) = 32
class item
{
int a;
base b;
int c;
public:
template <typename T>
inline T GetDerived()
{
return reinterpret_cast<T>(&b);
}
};
#pragma pack (pop)
int main()
{
cout << "ItemUnit :" << sizeof(base) << endl;
cout << "derived01 :" << sizeof(derived01) << endl;
cout << "derived02 :" << sizeof(derived02) << endl;
cout << "item :" << sizeof(item) << endl;
// I want to get Derived Class like this..
//item* i = new item();
//derived02 d = i.GetDerived<derived02>();
return 0;
}
and, it seemed to work as expected.. In LINUX.. (g++ 7.4)
# ./a
ItemUnit :32
derived01 :32
derived02 :32
item :40
but in MSVS2019, it returned..
ItemUnit :32
derived01 :32
derived02 :32
item :96
I also thought about other ways, but they have some....
UNION but, it cant using inheritance.. and I think it inconvenient to use.
make base class having char[32].. and derived having only functions to get,set using offset..
Is there any other good way?
please advice..

Related

about the sizeof winrt Demo object

I'm curious about the size of a very simple Demo object , so , I'm writing the following code
#include <windows.h>
#include "winrt/base.h"
#include <iostream>
#pragma comment(lib, "windowsapp")
/*
cl /nologo /await /std:c++latest /wd4002 /EHsc base_so.cpp
*/
using namespace std;
using namespace winrt;
using namespace winrt::impl;
struct IDemo;
template <typename D>
struct consume_IDemo
{
void hello();
};
template <> struct consume<IDemo> { template <typename D> using type = consume_IDemo<D>; };
template <typename D> void consume_IDemo<D>::hello()
{
WINRT_SHIM(D)->hello();
}
struct WINRT_EBO __declspec(uuid("3A44B7CC-9CB6-4512-8CAD-6400E662D865"))
IDemo : Windows::Foundation::IInspectable, consume_t<IDemo>
{
IDemo(std::nullptr_t = nullptr) noexcept {};
};
template <> struct abi<IDemo>
{
struct type : IInspectable
{
virtual HRESULT hello() = 0;
};
};
template <typename D>
struct produce<D,IDemo> : produce_base<D,IDemo>
{
HRESULT hello() override
{
shim().hello();
return S_OK;
}
};
struct Demo : implements<Demo,IDemo>
{
Demo()
{
cout << "sizeof Demo 0x" << hex << sizeof(*this) << dec << endl;
cout << "sizeof m_references 0x" << hex << sizeof(std::atomic<std::conditional_t<1, uintptr_t, uint32_t>>) << dec << endl;
cout << "is_composing " << is_composing << endl;
cout << "outer " << outer() << endl;
}
HRESULT hello()
{
cout << __FUNCTION__ << endl;
return S_OK;
}
};
int main()
{
Demo d;
}
and the output is
sizeof Demo 0x18
sizeof m_references 0x8
is_composing 0
outer 0000000000000000
I think the sizeof Demo should be 0x10 (64 machine) : sizeof(m_references)+sizeof(produce<Demo,IDemo>) , so , what is the extra 8 bytes ? many thanks!
It's either padding or v-tables. Maybe both...
The compiler is likely to insert a v-table pointer for each base class that has at least one virtual method declared. (And as an aside, when you do a C-cast, static_cast, or dynamic_cast from the concrete class to the non-first base class, the compiler will change the pointer value to that of the base-class or its v-table.)
Let's break it down.
Demo inherits from implements<Demo,IDemo>
implements is defined as follows:
struct implements : impl::producers<D, I...>, impl::base_implements<D, I...>::type
{
Now we're getting into WinRT noise. But it does seem to suggest multiple-inheritance. But it's just easier to break this out it the debugger.... There you go. The first vtable is for IUnknown. The other is something related to IInspectable.
So it makes sense. Each v-table is an 8 byte pointer. And the m_references is also 8 bytes. 8+8+8 = 24 = 0x18

How to access data type of a class declared in one class into another class (both in different translation unit)?

I have 5 files. (1. A.hpp, A.cpp : 2. B.hpp, B.cpp : 3 main.cpp)
// A.hpp
#ifndef MY_CLASS_A
#define MY_CLASS_A
#include <iostream>
class B; // forward declaration so that I could do B * b;
struct s {
int x;
double y;
};
class A{
s my_struct;
int size;
B * b;
public:
A(int, double, int);
void f1(s);
void f2(); // this function calls B's f1 function
s get_struct();
int get_size();
void print();
};
#endif
Then I have its implementation as
// A.cpp
#include "A.hpp"
#include "B.hpp"
A::A(int x_, double y_, int size_):my_struct({x_, y_}), size(size_){}
void A::f1(s s_){
// do stuff
s_.x = 5;
s_.y = 51.99;
}
void A::f2(){
int val;
// Here I am calling B's f1 function
val = b->f1(my_struct);
}
s A::get_struct(){
return my_struct;
}
int A::get_size(){
return size;
}
void A::print(){
std::cout << " ----- " << std::endl;
std::cout << "x = " << my_struct.x << std::endl;
std::cout << "y = " << my_struct.y << std::endl;
std::cout << "size = " << size << std::endl;
std::cout << " ----- " << std::endl;
}
Then I have B
//B.hpp
#ifndef MY_CLASS_B
#define MY_CASS_B
#include "A.hpp" // I placed here A.hpp because I am
// trying to use A's struct type
class A;
class B{
public:
int f1(s); // A's struct use here to get struct by value
};
#endif
and its implementation as
// B.cpp
#include "B.hpp"
// used A's struct here again
int B::f1(s my_struct){
std::cout << "*****" << std::endl;
std::cout << my_struct.x << std::endl;
std::cout << my_struct.y << std::endl;
std::cout << "*****" << std::endl;
}
finally main as
// main.cpp
// As per comment I should place #include "A.hpp" here
#include "A.cpp"
int main(){
A a(4,9.9, 5);
a.print();
return 0;
}
My main question is how can I access the struct declared in class A into class B?
I have tried to use forward declaration by failed miserably.
Open your C++ book to the chapter on pointers and references, and read that chapter again.
"The struct declared in class A" is my_struct, which is a private class member.
To have it accessible elsewhere, you need to pass it by reference.
int B::f1(const s &my_struct){
std::cout << "*****" << std::endl;
std::cout << my_struct.x << std::endl;
std::cout << my_struct.y << std::endl;
std::cout << "*****" << std::endl;
}
Now, when you invoke this from A:
val = b->f1(my_struct);
This will now pass a reference to the my_struct member, instead of making a copy of it.
Note that the parameter is declared as a reference to a const instance of s, because f1() does not need to modify it. If it does, simply pass it as a non-const reference:
int B::f1(s &my_struct){
Now, f1() will be able to modify my_struct, and end up modifying this private instance of A's class, that was passed to it.
P.S. This has nothing to do with different translation units. Whether this whole thing is in one translation unit, or is split across half a dozen of them, classes and references work the same way.

Accessing struct and union member functions within a class

In this program I just want to test a structure and union within a class itself.
I had created a public struct, and declared a union within it.
I am using Visual Studio and Qt Creator to type this code.
I want to ask, is defining a struct within a class good and accessible?
I am having problem with that.
If this is correct, how could I access the method or data member of the struct from main?
I'd also like to use the union member of the struct.
If the method or functions of the struct are not accessible this way,. what's another way of doing it?
//************************************************************************************
#ifndef CTEST_H
#define CTEST_H
class CTest {
int value;
public:
CTest(int);
int getValue();
struct CTESTSTRUCT {
union CTESTUNION
{
enum CTestEnum {
var1 = 1
};
char varChar1 = 'Y';
char varChar2 /*= 'N'*/; //union atmost have one field initializer
};
int structValue();
int testVal;
};
~CTest();
};
#endif
//************************************************************************************
#include <iostream>
#include "CTest.h"
CTest::CTest(int argVal) : value(argVal) {
std::cout << "Constructor Called" << std::endl;
}
int CTest::getValue() {
std::cout << "getValue Called" << std::endl;
return value;
}
int CTest::CTESTSTRUCT::structValue() {
std::cout << "CTESTSTRUCT::setValue Called" << std::endl;
return CTESTSTRUCT::CTESTUNION::var1;
}
CTest::~CTest() {
std::cout << "Distructor Called" << std::endl;
}
//*********************************************************************************
#include <iostream>
#include "CTest.h"
using namespace std;
CTest * ctestObj;
int main() {
ctestObj = new CTest(25);
int returnVal = ctestObj->getValue();
std::cout << "Value Returned: " << returnVal << std::endl;
std::cout << "structVal: " << std::endl;
//CTest::CTESTSTRUCT::testVal = 10;
delete ctestObj;
return 0;
}
What you're actually trying to do is have an instance of a struct inside your class. What you did was define a class within your class (which did not actually give your class a member of that type, but only scoped its definition).
So what you need to do is pull our the struct, from the class:
struct CTESTSTRUCT
{
// ...
};
And then give CTest a member of type CTESTSTRUCT
class CTest {
int value;
public:
CTest(int);
int getValue();
CTESTSTRUCT test;
~CTest();
};
Now you can access it like so:
int main() {
CTest * ctestObj;
ctestObj = new CTest(25);
int returnVal = ctestObj->getValue();
std::cout << "Value Returned: " << returnVal << std::endl;
std::cout << "structVal: " << std::endl;
ctestObj->test.testVal = 10;
delete ctestObj;
return 0;
}

C++ - friend functions

I am trying to make a simple friend function work, but not in just one source file. I seem to get an error and I can't seem to find an answer why.
Please have a look at my code:
----------classOne.h--------------
#ifndef CLASSONE_H_
#define CLASSONE_H_
using namespace std;
class ClassOne {
private:
int m_a;
int m_b;
public:
ClassOne(int a, int b);
void printValuesOne();
friend void ClassTwo::twoPrintsOne();
};
-
----------classOne.cpp------------
#include <iostream>
#include "classOne.h"
using namespace std;
ClassOne::ClassOne(int a, int b) {
m_a = a;
m_b = b;
}
void ClassOne::printValuesOne() {
cout << "m_a: " << m_a << " " << "m_b: " << m_b << endl;
}
.
----------classTwo.h-------------
#ifndef CLASSTWO_H_
#define CLASSTWO_H_
using namespace std;
class ClassTwo {
private:
int m_c;
int m_d;
public:
ClassTwo(int c, int d);
void printValuesTwo();
twoPrintsOne();
};
#endif
-
---------classTwo.cpp-----------
#include <iostream>
#include "classTwo.h"
using namespace std;
ClassTwo::ClassTwo(int c, int d) {
m_c = c;
`enter code here`m_d = d;
}
void ClassTwo::printValuesTwo() {
cout << "m_c: " << m_c << " " << "m_d: " << m_d << endl;
}
void twoPrintsOne() {
cout << "ClassTwo: " << m_a: " << m_a << " " << "m_b: " << m_b << endl;
}
Basically ClassOne and ClassTwo are the same sort of thing, but only one of ClassTwo's method has access to all of ClassOne's members, so ClassTwo can print ClassOne's member variables. However, when I try to compile the whole program (I haven't provided the main method here), I get this error an error:
classOne.h:19:15: error: ‘ClassTwo’ has not been declared
friend void ClassTwo::twoPrintsOne();
^
Can someone help and explain?
ClassOne doesn't know about ClassTwo, therefore it cannot befriend with any of its methods. You have to add:
#include "classTwo.h"
on top of your classOne.h.
You are getting confused with what "friend" is supposed to do.
"friending" ClassTwo will allow ClassTwo to access the private members of ClassOne as if they were public.
It will not link those members between the two classes in any way.
You could have ClassTwo inherit from ClassOne, or add a ClassOne member in ClassTwo

Static Data Members

Please have a look at the following code
GameObject.h
#pragma once
class GameObject
{
public:
GameObject(int);
~GameObject(void);
int id;
private:
GameObject(void);
};
GameObject.cpp
#include "GameObject.h"
#include <iostream>
using namespace std;
static int counter = 0;
GameObject::GameObject(void)
{
}
GameObject::GameObject(int i)
{
counter++;
id = i;
}
GameObject::~GameObject(void)
{
}
Main.cpp
#include <iostream>
#include "GameObject.h"
using namespace std;
int main()
{
//GameObject obj1;
//cout << obj1.id << endl;
GameObject obj2(45);
cout << obj2.id << endl;;
// cout << obj2.counter << endl;
GameObject obj3(45);
GameObject obj4(45);
GameObject obj5(45);
//Cannot get Static value here
//cout << "Number of Objects: " << GameObject
//
system("pause");
return 0;
}
Here, I am trying to record how many instances have been created. I know it can be done by a static data member, but I can't access it withing the Main method! Please help!
PS:
I am seeeking for a direct access, without a getter method
Your static variable, counter cannot be accessed because it isn't a member of GameObject. If you want to access the counter, you'll need to do something like this:
GameObject.h
#pragma once
class GameObject
{
public:
...
static int GetCounter();
...
};
GameObject.cpp
int GameObject::GetCounter()
{
return counter;
}
Then you can access the variable like:
cout << "Number of Objects: " << GameObject::GetCounter();
Of course, there are other ways of accessing a static variable, such as making the counter variable a static member of your GameObject class (which I would recommend).
In your code, counter is not a static member of your class, but just a good old global variable. You can read up on how to declare static member variables anywhere on the net, but here are some snippets:
GameObject.h
#pragma once
class GameObject
{
public:
GameObject(void);
GameObject(int);
~GameObject(void);
private:
int id;
// static members
public:
static int counter; // <<<<<<<<<<< declaration
};
ameObject.cpp
#include "GameObject.h"
int GameObject::counter = 0; // <<<<<<<<<<< instantiation
GameObject::GameObject(void)
{
counter++;
}
GameObject::GameObject(int i)
{
counter++;
id = i;
}
GameObject::~GameObject(void)
{
}
Main.cpp
#include <iostream>
#include "GameObject.h"
using namespace std;
int main()
{
GameObject obj2(45);
cout << "version one: " << obj2.counter << endl;
// second version:
cout << "version two: " << GameObject::counter << endl;
system("pause");
return 0;
}
Afaik accessing static members on an instance of that class should work fine, but it gives the wrong impression, you should prefer version two.
Never mind, I did it with a getter method. Closing thread