I have
// file BoardInitializer.h
#include <stdio.h>
#include <tchar.h>
#include <string>
#include <iostream>
using namespace std;
class BoardInitializer
{
static int *beginBoard;
static int *testBoard;
static void testBoardInitialize();
}
// file mh.cpp
#include "BoardInitializer.h"
int main(int argc, char* argv[])
{
BoardInitializer.testBoardInitialize();
return 0;
}
and I implemented BoardInitializer::testBoardInitialize in mh.cpp.
But I get the error "Function is inaccessible". What's wrong?
The default protection level for a class in C++ is private (with
the others being public and protected). That means all your
members and your member function are private and only accessible by
other member functions of that class or friends (functions or classes)
of that class.
The function main is neither and you end up with the error.
C++ provides a handy shortcut (or C legacy cruft, depending on your
worldview) called struct, where the default protection level is
public.
class my_class {
public:
int my_int;
};
or
struct my_struct {
int my_int;
};
should show the difference.
Classes have implicit private access, you need to add an explicit public: statement before your method. Additionally its a static method and needs to be addressed using the :: operator.
Class elements are private by default. Write this:
class BoardInitializer
{
public:
static int *beginBoard;
static int *testBoard;
static void testBoardInitialize();
};
Struct elements are public by default. Write this:
struct BoardInitializer
{
static int *beginBoard;
static int *testBoard;
static void testBoardInitialize();
};
Static class elements must be accessed with :: operator.
You forgot to make the function public by adding public: at the start of your class definition.
Class properties are private by default. You have to add public: to your class.
As pointed out by everyone, class members are by default private.
If you want to make it accessible, just make them public.
If you still want to protect/abstract/hide your data members(here *beginBoard and testBoard) just make the function public like:
class BoardInitializer {
static int *beginBoard;
static int *testBoard;
public:
static void testBoardInitialize();
}
Another possibility (for those who come here in the future) is that you forgot the public keyword when inheriting. That is, you should have class Base: public Derived.
Related
I found a similar code like the one shown below, and two things confuse me. The first one, is it possible to have an object of the class, inside of the definition of the class, as in the example below in code 1? I though this was not possible, but maybe the static keyword is making this possible. Is this right? what is it actually happening here?
The second one, I learned that we can access static member variables and static member functions of a class just by calling the class name and the scope resolution operator (and the member we want). Apparently, the way described in code1 is an alternative manner of doing this. So, what is the main difference (or advantage) of doing it this way? In other words, what is the difference between code 1 and code 2?
//CODE 1
namespace LOGGER {
class Logger;
}
class LOGGER::Logger {
void foo(){}
public:
static Logger logger;
};
int main()
{
LOGGER::Logger::logger.foo();
}
//CODE 2
namespace LOGGER {
class Logger;
}
class LOGGER::Logger {
public:
static void foo(){}
};
int main()
{
LOGGER::Logger::foo();
}
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.
EG,
//this is myclass.h
class myclass
{
public:
int publicfunction();
private:
int myprivatefunction();
};
//myclass.cpp
#include "myclass.h"
int myclass::publicfunction()
{myprivatefunction();
blabla...}
int myclass::privatefunction()
{blabla...}
So, for users can access the class,we will provide the header file to the users. But shouldn't we conceal the internal implement details of the class??? I mean, when the users get myclass.h, they will find that the class contains a private function myprivatefunction
You can export the private members inside a struct
//this is myclass.h
class myclass{
private:
struct myClassPrivateMembers;
myClassPrivateMembers* privParts;
public:
// ...
};
And in the *.cpp file:
//this is myclass.cpp
struct *myClassPrivateMembers{
int myprivatefunction();
}
myclass::myclass(){
privParts = new myClassPrivateMembers;
};
That way the user won't be able to see things you hidden inside myClassPrivateMembers, because they'll be inside the *.cpp file, not declared in the header file.
This is widelly known as the "pimpl" idiom.
Your header file isn't just your public interface. It's a description of your data layout for the compiler. It is perfectly normal that the private members get shown in the header file. private is not a security mechanism and never will be.
It's a bit strange, but it falls out from a simple yet efficient way of going about the problem.
You might as well separate your interface and your implementation.
myinterface.h
class myinterface
{
public:
virtual int publicfunction() = 0;
};
myclass.h
class myclass : public myinterface
{
public:
virtual int publicfunction();
private:
int privatefunction();
};
myclass.cpp
#include "myclass.h"
int myclass::publicfunction()
{myprivatefunction();
blabla...}
int myclass::privatefunction()
{blabla...}
You don't have to expose myclass.{h,cpp} to library users.
But this might be an overkill... (I would call this "Java folks' way")
I am currently doing a checker for the top level domains of email addresses. In order to check, I am comparing it to a list that is a text file. I want to import the list into a static map container. However, when I try to instantiate it, it says that it cannot be defined in the current scope. Why is that?
This is some my header file:
class TldPart {
public:
static void LoadTlds();
private:
static map<string,bool> Tld;
}
Here is the implementation in the cpp:
void TldPart::LoadTlds()
{
map<string,bool> Tld;
...
}
It is telling me that ValidTld cannot be defined in the LoadTlds function.
Static members of a class exist outside of an object. You should define and initialize static member outside of the class.
Here we define and initialize a static class member:
header-file:
#pragma once
#include <map>
#include <string>
class TldPart {
public:
static void LoadTlds();
private:
static std::map<std::string, bool> tld;
};
your cpp-file:
#include "external.h"
std::map<std::string,bool> TldPart::tld;
void TldPart::LoadTlds()
{
tld.insert(std::make_pair("XX", true));
}
And don't forget semicolon at the end of the class.
EDIT: You can provide in-class initializers for static members of const integral type or static members that are constexprs and has literal type.
I am trying to implement the following class. However, when I try to instantiate an object of the class within its definition and pass "0" as value to initialize the object, i get an error:
"a type specifier is expected".
Can anyone explain how can i remove this error?
class MessageType
{
public:
static const MessageType msgEvent(0);
private:
MessageType();
virtual ~MessageType();
MessageType(int);
};
You need to initialize(define) it outside the class definition in a cpp file.
MessageType const MessageType::msgEvent;
However, Your intent in doing so is not very clear. Are you trying to implement a Singleton Pattern, probably this sample implementation might help, I leave it to you to decide, whether you really need a singleton, inspite of its disadvantages:
//MessageType.h
#include <boost/noncopyable.hpp>
class MessageType: private boost::noncopyable
{
public:
static MessageType* instance();
private:
MessageType();
~MessageType();
static bool g_initialised;
// static initialisation
static MessageType g_instance;
// dynamic initialisation
};
// MessageType.cpp
#include "MessageType.hpp"
#include <ostream>
#include <iostream>
#include <cstring>
bool MessageType::g_initialised;
// static initialisation
MessageType MessageType::g_instance;
// dynamic initialisation
MessageType::MessageType()
{
g_initialised = true;
}
MessageType::~MessageType()
{
g_initialised = false;
}
MessageType* MessageType::instance()
{
return g_initialised ? &g_instance : 0;
}
You can only initialize static member variables in the definition if they are of int type.
class MessageType
{
public:
static int sCount = 0; // That is fine.
static std::string sLogName; // That is fine.
static std::string sLogName("log.txt"); // Fail!
};
There's no way around this rule. If you want to initialize a static member variable, then you have to do it in the cpp:
std::string MessageType::sLogName("log.txt"); // fine, in the cpp.
This same rule applies directly to your MessageType instance, and has nothing to do with the fact that the class is of it's own type.