I have header.h
Class A
{
int var_1;
int var_2;
};
Class b
{
private: static A var[MAX];
.....
};
But how can I initialize this property in header.cpp?
Give A a default constructor that sets the ints to 0s or something.
A b::var[MAX] = {};
In implementation file:
A b::var[] = {}; // static member definition
// A() is called for each member so you might want
// to implement it
example:
#define MAX 10
class A
{
int var_1;
int var_2;
};
class b
{
private:
static A var[MAX]; // static member declaration
};
A b::var[] = {}; // static member definition
int main() {
return 0;
}
http://ideone.com/ndkPmX
Assuming there is class A with the public constructor that takes no arguments (or default constructor):
File b.h :
#include "a.h"
// global constant:
const int MAX = 10;
class B {
private:
static A var[MAX]; // declaration
};
File b.cpp :
#include "b.h"
A B::var[MAX] = {}; // definition
Related
I have a a.h which has a class d. I am wondering how to make a shorthand way to use the struct 'a' inside of my class.
//a.h
class d
{
public:
struct a
{
int val;
}
};
//a.cpp
#include "a.h"
using d::a; //line with error
a methodName()
{
//does stuff
return object_of_type_a;
}
what about this one
class d
{
public:
struct a
{
int val;
};
};
typedef struct d::a da;
I have the following code:
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
class A {
public:
int f();
int (A::*x)();
};
int A::f() {
return 1;
}
int main() {
A a;
a.x = &A::f;
printf("%d\n",(a.*(a.x))());
}
Where I can initialize the function pointer correctly. But I want to make the function pointer as static, I want to maintain single copy of this across all objects of this class.
When I declare it as static
class A {
public:
int f();
static int (A::*x)();
};
I am unsure of the way/syntax to initialize it to function f. Any resource would be helpful
A static pointer-to-member-function (I guess you already know this is different from a pointer to a static member function) is a kind of static member data, so you have to provide a definition outside the class like you would do with other static member data.
class A
{
public:
int f();
static int (A::*x)();
};
// readable version
using ptr_to_A_memfn = int (A::*)(void);
ptr_to_A_memfn A::x = &A::f;
// single-line version
int (A::* A::x)(void) = &A::f;
int main()
{
A a;
printf("%d\n",(a.*(A::x))());
}
How do I initialize pointer class B foo inside class A? I am new to C++.
Header.h
namespace Core
{
enum type
{
Left, Right
};
template<type t>
class B
{
public:
B(int i);
private:
type dir;
int b = 12;
};
class A
{
public:
B<Left> *foo;
};
}
Source.cpp
namespace Core
{
template<type t>
B<t>::B(int i)
{
dir = t;
b = i;
}
}
int main()
{
Core::A *a = new Core::A;
a->foo = new Core::B<Core::Left>(10);
return 0;
}
Source.cpp needs a #include "Header.h" statement, and Header.h needs a header guard.
Also, you need to move the implemention of B's constructor into the header file. See Why can templates only be implemented in the header file?.
Try this:
Header.h:
#ifndef HeaderH
#define HeaderH
namespace Core
{
enum type
{
Left, Right
};
template<type t>
class B
{
public:
B(int i);
private:
type dir;
int b = 12;
};
class A
{
public:
B<Left> *foo;
};
template<type t>
B<t>::B(int i)
{
dir = t;
b = i;
}
}
#endif
Source.cpp
#include "Header.h"
int main()
{
Core::A *a = new Core::A;
a->foo = new Core::B<Core::Left>(10);
//...
delete a->foo;
delete a;
return 0;
}
I would suggest taking it a step further by inlining B's constructor and giving A a constructor to initialize foo:
Header.h:
#ifndef HeaderH
#define HeaderH
namespace Core
{
enum type
{
Left, Right
};
template<type t>
class B
{
public:
B(int i)
{
dir = t;
b = i;
}
private:
type dir;
int b = 12;
};
class A
{
public:
B<Left> *foo;
A(int i = 0)
: foo(new B<Left>(i))
{
}
~A()
{
delete foo;
}
};
}
#endif
Source.cpp
#include "Header.h"
int main()
{
Core::A *a = new Core::A(10);
//...
delete a;
return 0;
}
How do I initialize pointer class B foo inside class A?
Option 1
Construct a B<Left> with an assumed value.
class A
{
public:
B<Left> *foo = new B<Left>(0);
};
Option 2
Add a constructor of A that accepts an int that can be used to construct a B<Left> .
class A
{
public:
A(int i) : foo(new B<Left>(i)) {}
B<Left> *foo;
};
Word of caution
Before you down too far into using pointers to objects in your classes, consider the following:
What is The Rule of Three?
https://en.cppreference.com/w/cpp/memory, specially shared_ptr and unique_ptr.
I recently got stuck in a situation like this:
class A
{
public:
typedef struct/class {…} B;
…
C::D *someField;
}
class C
{
public:
typedef struct/class {…} D;
…
A::B *someField;
}
Usually you can declare a class name:
class A;
But you can't forward declare a nested type, the following causes compilation error.
class C::D;
Any ideas?
You can't do it, it's a hole in the C++ language. You'll have to un-nest at least one of the nested classes.
class IDontControl
{
class Nested
{
Nested(int i);
};
};
I needed a forward reference like:
class IDontControl::Nested; // But this doesn't work.
My workaround was:
class IDontControl_Nested; // Forward reference to distinct name.
Later when I could use the full definition:
#include <idontcontrol.h>
// I defined the forward ref like this:
class IDontControl_Nested : public IDontControl::Nested
{
// Needed to make a forwarding constructor here
IDontControl_Nested(int i) : Nested(i) { }
};
This technique would probably be more trouble than it's worth if there were complicated constructors or other special member functions that weren't inherited smoothly. I could imagine certain template magic reacting badly.
But in my very simple case, it seems to work.
If you really want to avoid #including the nasty header file in your header file, you could do this:
hpp file:
class MyClass
{
public:
template<typename ThrowAway>
void doesStuff();
};
cpp file
#include "MyClass.hpp"
#include "Annoying-3rd-party.hpp"
template<> void MyClass::doesStuff<This::Is::An::Embedded::Type>()
{
// ...
}
But then:
you will have to specify the embedded type at call time (especially if your function does not take any parameters of the embedded type)
your function can not be virtual (because it is a template)
So, yeah, tradeoffs...
I would not call this an answer, but nonetheless an interesting find:
If you repeat the declaration of your struct in a namespace called C, everything is fine (in gcc at least).
When the class definition of C is found, it seems to silently overwrite the namspace C.
namespace C {
typedef struct {} D;
}
class A
{
public:
typedef struct/class {...} B;
...
C::D *someField;
}
class C
{
public:
typedef struct/class {...} D;
...
A::B *someField;
}
If you have access to change the source code of classes C and D, then you can take out class D separately, and enter a synonym for it in class C:
class CD {
};
class C {
public:
using D = CD;
};
class CD;
This would be a workaround (at least for the problem described in the question -- not for the actual problem, i.e., when not having control over the definition of C):
class C_base {
public:
class D { }; // definition of C::D
// can also just be forward declared, if it needs members of A or A::B
};
class A {
public:
class B { };
C_base::D *someField; // need to call it C_base::D here
};
class C : public C_base { // inherits C_base::D
public:
// Danger: Do not redeclare class D here!!
// Depending on your compiler flags, you may not even get a warning
// class D { };
A::B *someField;
};
int main() {
A a;
C::D * test = a.someField; // here it can be called C::D
}
This can be done by forward declare the outer class as a namespace.
Sample: We have to use a nested class others::A::Nested in others_a.h, which is out of our control.
others_a.h
namespace others {
struct A {
struct Nested {
Nested(int i) :i(i) {}
int i{};
void print() const { std::cout << i << std::endl; }
};
};
}
my_class.h
#ifndef MY_CLASS_CPP
// A is actually a class
namespace others { namespace A { class Nested; } }
#endif
class MyClass {
public:
MyClass(int i);
~MyClass();
void print() const;
private:
std::unique_ptr<others::A::Nested> _aNested;
};
my_class.cpp
#include "others_a.h"
#define MY_CLASS_CPP // Must before include my_class.h
#include "my_class.h"
MyClass::MyClass(int i) :
_aNested(std::make_unique<others::A::Nested>(i)) {}
MyClass::~MyClass() {}
void MyClass::print() const {
_aNested->print();
}
I'm trying to create static constant that will be named the same in different classes and can be accessed from other classes
I'm trying to access to the constant from other classes like that B::num
My code:
main.cpp
...
Ptr ptr;
A *a = C::make(ptr);
A.h
class A { //pure virtual
public:
virtual void func()=0;
virtual void func2()=0;
protected:
Ptr ptr;
}
B.h
class B : public A {
public:
B();
static unsigned char const num[2];
...
}
B.cpp
#include "B.h"
constexpr unsigned char B::num[]={0x4,0x5};
B::B(){..}
C.h
#include "A.h"
#include "B.h"
class C {
public:
static A* make(const Ptr &);
}
C.cpp
A *C::make(const Ptr &ptr){
if(!memcmp(ptr.memory,B::num,sizeof(B::num))){
...
}
}
errors
B.h file - error: from previous declaration 'B::num'
B.cpp file - error: redeclaration B::num differs in 'constexpr'
What is the problem?
Thanks.
First problem : you defined an unrelated, global a. The one you're trying to define is scoped inside the class(es).
static constexpr unsigned char class1::a[2] = {0x4,0x5};
// ^^^^^^^^
Second problem : defintions belong in .cpp files, not headers.
Here is an example of static const a in 2 classes :
#include <iostream>
class class1 {
public:
static unsigned char const a[2];
};
class class2 {
public:
static unsigned char const a[2];
};
constexpr unsigned char class1::a[] = {0x4,0x5};
constexpr unsigned char class2::a[] = {0x4,0x5};
int main() {
std::cout << static_cast<unsigned>(class1::a[0])
<< static_cast<unsigned>(class2::a[1]) << std::endl;
return 0;
}
Note:
the declaration contains static and const and should be in a .h file
the definition constains constexpr and should be in a .cpp