I was programming Vulkan based renderer but unfortunately this error appeared:
'Azazel::Instance::~Instance': cannot access private member declared in class 'Azazel::Instance'
It gives me a headache. I tried to predeclare Azazel_Menager class at start of my namespace,
but it did not work as well so I changed:
friend class Azazel_Menager;
to:
friend class Azazel::Azazel_Menager;
well it did not do the trick as well. So here I'm asking for your help.
maybe you will see something I did not.
Azazel_Menager:
#pragma once
#include "Engine/Core/UsingTypes.h"
namespace Azazel
{
class Instance;
class PhysicalDevice;
class Azazel_Menager
{
public:
static void CreateInstance();
static void RetrieveAndSetPhysicalDevice();
private:
static Ref<Instance> s_Instance;
static Ref<PhysicalDevice> s_PhysicalDevice;
};
}
Instance.h:
#pragma once
#include <vector>
#include <VulkanSDK/include/vulkan/vulkan.hpp>
namespace Azazel
{
class Azazel_Menager;
class Instance
{
friend class Azazel::Azazel_Menager;
private:
Instance();
~Instance();
public:
vk::UniqueInstance m_Instance;
VkDebugUtilsMessengerEXT m_callback;
};
}
Ref = std::shared_ptr
You probably use constructor/destructor outside of Azazel_Menager (as in std::make_shared or in default Deleter).
You have to use them exclusively in Azazel_Menager, as:
void Azazel_Menager::CreateInstance()
{
s_Instance = std::shared_ptr<Azazel::Instance>{new Azazel::Instance{},
[](auto* p){ delete p; }};
}
Demo
Related
I'm having an odd issue where when I forward declare a class and run it, it calls the constructor successfully but when it tries to work with a shared_ptr, it segfaults within the __exchange_and_add on return __atomic_fetch_add forward declared class constructor.
The class we're trying to use is located in a linked shared object.
For example:
class MyForwardDeclaredClass {
public:
MyForwardDeclaredClass();
}
namespace MyNamespace
{
class MyClass
{
public:
MyClass() { _myForwardDeclaredClass.reset(new MyForwardDeclaredClass()); }
std::shared_ptr<MyForwardDeclaredClass> _myForwardDeclaredClass;
}
}
But if I do this:
#include <MyForwardDeclaredClass.hpp>
namespace MyNamespace
{
class MyClass
{
public:
MyClass() { _myForwardDeclaredClass.reset(new MyForwardDeclaredClass()); }
std::shared_ptr<MyForwardDeclaredClass> _myForwardDeclaredClass;
}
}
It works properly.
I create a basic IBasic interface with a static field
class IBasic
{
public:
IBasic();
virtual ~IBasic();
static std::vector< std::vector<char> > Field;
};
from which the Inherit class is inherited:
class Inherit : public IBasic
{
public:
Inherit(int);
~Inherit();
void Foo();
};
The Inherit class makes some manipulations with Field static member in constructor/or member function.
In order to create an instance of the Inherit class, we need to explicitly declare a static field in the main.cpp before the main function:
#include "Basic.h"
#include "Inherit.h"
std::vector< std::vector<char> > IBasic::Field;
int main()
{
Inherit(10);
return 0;
}
The questions are:
In what namespace does the static method actually exists (global?)? Because I know that static field/function is not a class member in fact.
Is there another way to declare this static method, for example, in a
class file, inside a main function, or through creation unnamed namespace? Is it only one right variant?
How is right? What should be considered first of all?
A static member of a class is a member of its class (that's a tautology) and its class namespace (a class is a namespace). It is not a nember of any other namespace.
A non-const static data member of a class must be defined exactly once in a program, outside of any class, in the same namespace its class is defined in (a global namespace in your case). A header file is inappropriate place for such declaration. It is normally placed in an implementation .cpp file that goes together with the header file.
Having said that, an interface should not have any static data members, much less public ones. It is most likely a grave design error.
In what namespace does the static method actually exists (global?)? Because I know that static field/function is not a class member in fact.
It is declared in scope of the class. In fact the static variable is a class member, your assumption is wrong.
Is there another way to declare this static method, for example, in a class file, inside a main function, or through creation unnamed namespace? Is it only one right variant?
The usual way is to define it in the translation unit that contains the function definitions for the class.
How is right? What should be considered first of all?
There's no right or wrong way, but as mentioned definition in the same translation unit as the class function definitions is the usual way.
Here's an example usage of a static member without any inheritance.
SomeClass.h
#ifndef SOME_CLASS_H
#define SOME_CLASS_H
class SomeClass {
private:
int x;
public:
static SomeClass* const get(); // Needed For Using class to get this pointer
SomeClass();
int getX() const { return x; }
void setX( int val ) { x = val; }
};
#endif // SOME_CLASS_H
SomeClass.cpp
#include "SomeClass.h"
static SomeClass* s_pSomeClass = nullptr;
SomeClass::SomeClass() {
s_pSomeClass = this;
}
SomeClass* const SomeClass::get() {
if ( nullptr == s_pSomeClass ) {
// throw exception
}
return s_pSomeClass;
}
Another class using above class as a static member
OtherClass.h
#ifndef OTHER_CLASS_H
#define OTHER_CLASS_H
class SomeClass; // Forward Declaration
class OtherClass {
private:
static SomeClass* pSomeClass; // The Static Member to this class
int y;
public:
OtherClass();
int getY() const { return y; }
void setY( int val ) { y = val; }
void useSomeClassToSetY();
};
#endif // OTHER_CLASS_H
OtherClass.cpp
#include "OtherClass.h"
#include "SomeClass.h"
SomeClass* OtherClass::pSomeClass = nullptr;
OtherClass::OtherClass() {
if ( nullptr == pSomeClass ) {
pSomeClass = SomeClass::get();
}
}
void OtherClass::useSomeClassToSetY() {
// First Set X To Some Value:
pSomeClass->setX( 10 ); // Use of Static Member
y = pSomeClass->getX(); // Use of Static Member
}
Static members still belong to the class, but they have static storage.
I'm having a compilation error using Apple's Clang 7.0 with the following friendship code, using C++11 standard. I wonder what's really wrong with it since it seems to be valid for me. I'm describing the setting and the error I'm having:
MyInterface
namespace namespace1
{
class MyInterface
{
friend class MyClass;
public:
virtual void some_method(void) = 0;
...
private:
type some_attribute;
...
}
}
MyClass::MyMethod Implementation
namespace namespace2
{
void MyClass::MyMethod(MyInterface* MyConcrete)
{
...
// MyConcrete implements MyInterface
if(MyConcrete->some_attribute == some_value) // Error*
{
...
}
...
}
}
Error
error: 'some_attribute' is a private member of 'namespace1::MyInterface'
I really expected that MyClass would have access to some_attribute in MyConcrete (which implemented MyInterface) regardless of the class access modifier. Any clues why this error is happening? Any suggestions?
Thank you!
MyClass is in namespace2. So you need to use:
friend class namespace2::MyClass;
You may also need to use forward decleration of MyClass before you define MyInterface.
Here's an example that compiles:
// forward decleration
namespace namespace2
{
class MyClass;
}
namespace namespace1
{
class MyInterface
{
friend class namespace2::MyClass; // added missing namespace
public:
virtual void some_method(void) = 0;
private:
int some_attribute;
};
}
namespace namespace2
{
class MyClass
{
void MyMethod(namespace1::MyInterface* MyConcrete)
{
if(MyConcrete->some_attribute == 1)
{
}
}
};
}
int main()
{
}
You can run it here.
friend class MyClass; in the context of ::namespace1::MyInterface refers to the class ::namespace1::MyClass, which is a different class from ::namespace2::MyClass. (That's the whole point of namespaces, right?)
Change the friend declaration to read like this:
friend class ::namespace2::MyClass;
Note that this requires that the type ::namespace2::MyClass has already been declared, so you either need to forward-declare it (namespace namespace2 { class MyClass; }) or you need to make sure that the definition is included prior to the definition of ::namespace1::MyInterface.
(See this demo.)
I have an issue when trying to initialize static members of a static class template.
Basically, what I thought this approach would be useful for:
I have a lot of objects, which are of course all of the same Base type but they have differing object types. I just want to manipulate these objects, that's why I decided to use a static template as there are quite a number of different types these object can consist of.
However, for logging and options passing I wanted to add the corresponding members to the template whithout having to write initializers for every derived static class.
Please note that the following code is not actually working, because there is some SDK involved.
I'm just aksing for the right approach, not right code.
Thanks in advance. :)
template.h:
#ifndef _TEMPLATE_H
#define _TEMPLATE_H
#include "stats.h"
template<class T>
class TemplateObj
{
public:
static void SetParameters(const Options& options)
{
T::_options = options; // Is this even possible?
T::Init();
T::DoStuff(_options);
}
protected:
static void Message() { stats.Print("Message from Template static method"); }
static Stats& TemplateObj<T>::stats = Stats::GetInstance(); // This will not work as this is a non-trivial initializer, how to do it correctly? Stats::GetInstance() retrieves a singleton instance
static Options& TemplateObj<T>::_options; // Possible?
};
#endif
derived.h:
#ifndef _DERIVED_H
#define _DERIVED_H
#include "template.h"
class Derived :TemplateObj < Derived >
{
public:
static void Init();
static void DoStuff(Options& options)
};
#endif
derived.cpp:
#include "derived.h"
void Derived::Init()
{
// Init stuff here
TemplateObj::Message(); // Call static method from template directly
}
void Derived::DoStuff(Options& options)
{
// Do something with options
stats.Print("Message from derived static method."); // Access to "stats" here. "stats" should be declared and initialized inside the template.
options.Load(); // Example
}
main.h
#include "derived.h"
main()
{
TemplateObj<Derived>::SetParameters(new Options);
}
Basically, you don't need to put TemplateObj<T>:: before the function definition if it is inside the class definition. The following two are both valid:
template<class T>
class A{
void func( void );
};
template<class T>
void A<T>::func() { /* Okay */ }
template<class T>
class B {
void func( void ){ /* Okay */ }
};
In your case, replace the following static Stats& TemplateObj<T>::stats = Stats::GetInstance(); with static Stats& stat() { return Stats::GetInstance(); }
And the following static Options& TemplateObj<T>::_options; with this static Options& _options;.
On the other hand, replace this T::_options = options; with TemplateObj<T>::_options = options;.
A C++ n00b question. Is it possible to call a private constructor from a static method defined in the cpp? I'd like to keep methods out of the header file if possible -- I figure there should be a way to do this. I'm getting an error when attempting this:
"cannot access private member declared in class SomeClass"
/////////////////
// SomeClass.h //
/////////////////
class SomeClass {
public:
static SomeClass SomeMethod();
private:
SomeClass(int i);
}
///////////////////
// SomeClass.cpp //
///////////////////
static SomeClass OSImplementation() {
return SomeClass(0);
};
// calls implementation
SomeClass SomeClass::SomeMethod() {
return OSImplementation();
}
You can make OSImplementation a friend method.
Or you can make OSImplementation a static method within the class (but that has to be declared in the header).
Or, probably the most common way to do this, is to have an internal implementation class, like this:
class SomeClass {
public:
//...
private:
struct Impl;
Impl* intern;
};
In your cpp file, you declare struct SomeClass::Impl.
In your constructor, create the SomeClass::Impl instance. Delete it in the destructor. And implement the copy-constructor and the assignment operator!
This is called the PIMPL (pointer to implementation) idiom (Wikipedia, c2.com). It's used a lot in big projects like Qt.
Yes, it is possible, by making the OSImplementation() friend of SomeClass. Next example compiles without warnings and errors using g++ 4.6.1 :
#include <iostream>
// declare in hpp
class SomeClass {
friend SomeClass OSImplementation();
public:
static SomeClass SomeMethod();
void foo();
private:
SomeClass(int);
};
int main()
{
auto obj = SomeClass::SomeMethod();
obj.foo();
}
// define in cpp
SomeClass SomeClass::SomeMethod(){
return SomeClass( 5 );
}
SomeClass::SomeClass(int){
}
void SomeClass::foo(){
std::cout<<"foo"<<std::endl;
}
SomeClass OSImplementation()
{
return SomeClass::SomeMethod();
}