Skip to main content
gamedev.net
🔒 Locked

initializing private array in a class

Started by Tradone Mar 21, 2006 at 8:44 PM 84 replies 17.7k views
Original Post
Tradone
Tradone

class Print {
	private:
		void PrintSoftwareInfo( std::string shenuVersion );
		void PrintCSS( std::map< std::string, std::string > para_fieldData );
		std::string shenuVersion;
		std::string CSSClasses[2][3];
		std::string CSSInstances[2][6];

/*
		std::string CSSClasses[2][3] = {
			{"Table", "A", "A:Hover"},
			{"Body", "Link", "Hover"} };
		std::string CSSInstances[2][6] = {
			{"Decoration", "Color", "Bgcolor", "Face", "Size", "Style"},
			{"text-decoration", "color", "background-color", "font-family", "font-size", "font-style"};
*

as you can see the commented out is what i want to do, but can not do. so instead I had to do this..

Print::Print(){
	shenuVersion = "7.000";
	CSSClasses[0][0]="Table";
	CSSClasses[0][1]="A";
	CSSClasses[0][2]="A:Hover";
	CSSClasses[1][0]="Body";
	CSSClasses[1][1]="Link";
	CSSClasses[1][2]="Hover";
	CSSInstances[0][0]="Decoration";
	CSSInstances[0][1]="Color";
	CSSInstances[0][2]="Bgcolor";
	CSSInstances[0][3]="Face";
	CSSInstances[0][4]="Size";
	CSSInstances[0][5]="Style";
	CSSInstances[1][0]="text-decoration";
	CSSInstances[1][1]="color";
	CSSInstances[1][2]="background-color";
	CSSInstances[1][3]="font-family";
	CSSInstances[1][4]="font-size";
	CSSInstances[1][5]="font-style";

}

crappy...
Adam Hamilton
Adam Hamilton
I don't know if this would work because I have never seen it done with std strings but you might try

class Print {	private:		void PrintSoftwareInfo( std::string shenuVersion );		void PrintCSS( std::map< std::string, std::string > para_fieldData );		const std::string CSSClasses[2][3] = {			{"Table", "A", "A:Hover"},			{"Body", "Link", "Hover"} };		const std::string CSSInstances[2][6] = {			{"Decoration", "Color", "Bgcolor", "Face", "Size", "Style"},			{"text-decoration", "color", "background-color", "font-family", "font-size", "font-style"};};


Give that a go... I just put const before the std::string and removed your previous declarators

Tradone
Tradone
i've tried it.
what's the difference though that the compiler won't let me ( to your logic )
i mean why do you think const would work and the other doesn't?

but im giving it another shot right now.
hopefully it works like magic!!!
Tradone
Tradone
cool.. longest compile error ever.
151# ./z
In file included from Document.h:8,
from new_shenu.cpp:2:
Print.h:18: error: a brace-enclosed initializer is not allowed here before '{' t oken
Print.h:20: error: ISO C++ forbids initialization of member CSSClasses'
Print.h:20: error: making
CSSClasses' static
Print.h:20: error: invalid in-class initialization of static data member of non- integral type const std::string[2][3]'
Print.h:21: error: a brace-enclosed initializer is not allowed here before '{' t oken
Print.h:42: error: ISO C++ forbids initialization of member
CSSInstances'
Print.h:42: error: making CSSInstances' static
Print.h:42: error: invalid in-class initialization of static data member of non- integral type
const std::string[2][6]'
In file included from new_shenu.cpp:2:
Document.h:18: error: field print' has incomplete type
new_shenu.cpp:5: error: expected nested-name-specifier before "namespace"
new_shenu.cpp:5: error: expected unqualified-id before "namespace"
new_shenu.cpp:5: error: expected
;' before "namespace"
new_shenu.cpp:5: error: expected unqualified-id before "namespace"
new_shenu.cpp:7: error: cannot declare member function Print::Document::Documen t' within Print'
new_shenu.cpp:52: error: cannot declare member function Print::Document::GetCon figData' within Print'
new_shenu.cpp:56: error: cannot declare member function Print::Document::SetCon figData' within Print'
new_shenu.cpp:76: error: cannot declare member function Print::Document::Tokeni ze' within Print'
new_shenu.cpp:118: error: expected }' at end of input
new_shenu.cpp:118: error: expected unqualified-id at end of input
new_shenu.cpp:118: error: expected
,' or ;' at end of input
In file included from Print.cpp:1:
Print.h:18: error: a brace-enclosed initializer is not allowed here before '{' t oken
Print.h:20: error: ISO C++ forbids initialization of member
CSSClasses'
Print.h:20: error: making CSSClasses' static
Print.h:20: error: invalid in-class initialization of static data member of non- integral type
const std::string[2][3]'
Print.h:21: error: a brace-enclosed initializer is not allowed here before '{' t oken
Print.h:42: error: ISO C++ forbids initialization of member CSSInstances'
Print.h:42: error: making
CSSInstances' static
Print.h:42: error: invalid in-class initialization of static data member of non- integral type const std::string[2][6]'
In file included from /usr/include/c++/3.4/backward/fstream.h:31,
from Skin.h:5,
from Print.cpp:2:
/usr/include/c++/3.4/backward/backward_warning.h:32:2: warning: #warning This fi le includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples in clude substituting the header for the header for C++ includes, or instead of the deprecated header . To disable this warning us e -Wno-deprecated.
In file included from /usr/include/c++/3.4/fstream:49,
from /usr/include/c++/3.4/backward/fstream.h:32,
from Skin.h:5,
from Print.cpp:2:
/usr/include/c++/3.4/bits/basic_file.h:47: error: expected unqualified-id before "namespace"
In file included from /usr/include/c++/3.4/backward/fstream.h:32,
from Skin.h:5,
from Print.cpp:2:
/usr/include/c++/3.4/fstream:52: error: expected unqualified-id before "namespac e"
In file included from /usr/include/c++/3.4/fstream:857,
from /usr/include/c++/3.4/backward/fstream.h:32,
from Skin.h:5,
from Print.cpp:2:
/usr/include/c++/3.4/bits/fstream.tcc:40: error: expected unqualified-id before "namespace"
In file included from Skin.h:5,
from Print.cpp:2:
/usr/include/c++/3.4/backward/fstream.h:34: error: using-declaration for non-mem ber at class scope
/usr/include/c++/3.4/backward/fstream.h:35: error: using-declaration for non-mem ber at class scope
/usr/include/c++/3.4/backward/fstream.h:36: error: using-declaration for non-mem ber at class scope
/usr/include/c++/3.4/backward/fstream.h:37: error: using-declaration for non-mem ber at class scope
/usr/include/c++/3.4/backward/fstream.h:38: error: using-declaration for non-mem ber at class scope
/usr/include/c++/3.4/backward/fstream.h:41: error: using-declaration for non-mem ber at class scope
/usr/include/c++/3.4/backward/fstream.h:42: error: using-declaration for non-mem ber at class scope
/usr/include/c++/3.4/backward/fstream.h:43: error: using-declaration for non-mem ber at class scope
/usr/include/c++/3.4/backward/fstream.h:44: error: using-declaration for non-mem ber at class scope
/usr/include/c++/3.4/backward/fstream.h:45: error: using-declaration for non-mem ber at class scope
In file included from /usr/include/c++/3.4/iterator:73,
from Skin.h:8,
from Print.cpp:2:
/usr/include/c++/3.4/bits/stream_iterator.h:42: error: expected unqualified-id b efore "namespace"
Print.cpp:149: error:
void Print::PrintCSS(std::map, std::allocator > >)' and void Print::PrintCSS(std::map, std::allocator > >)' cannot be overloaded
Print.cpp:218: error:
void Print::PrintSoftwareInfo(std::string)' and void Pri nt::PrintSoftwareInfo(std::string)' cannot be overloaded
Print.cpp:245: error: expected
}' at end of input
Print.cpp: In member function void Print::PrintCSS(std::map, std::allocator > >)':
Print.cpp:154: error:
CSSClasses' undeclared (first use this function)
Print.cpp:154: error: (Each undeclared identifier is reported only once for each function it appears in.)
Print.cpp:156: error: CSSInstances' undeclared (first use this function)
Print.cpp: At global scope:
Print.cpp:245: error: expected unqualified-id at end of input
Print.cpp:245: error: expected
,' or `;' at end of input
In file included from /usr/include/c++/3.4/backward/fstream.h:31,
from Skin.h:5,
from Skin.cpp:1:
/usr/include/c++/3.4/backward/backward_warning.h:32:2: warning: #warning This fi le includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples in clude substituting the header for the header for C++ includes, or instead of the deprecated header . To disable this warning us e -Wno-deprecated.
151#
Adam Hamilton
Adam Hamilton
No it won't work... I have just thought back to my reading. const only works for integral types like

class Foo {private:   const int bar=5;};


So I don't think strings count as integral types... Strangely, I don't think it works for floating point numbers

I think the compiler might somehow embed the numbers in to the allocated memory.

Edit: It would have been cool if the C++ compiler could do this.
smitty1276
smitty1276
You can't initialize the array in the class declaration. You declare it there, and you must initialize it in the constuctor. The class declaration pretty much just indicates how the data will be arranged in memory (in very simple terms).

Quote:

const only works for integral types


What? That isn't true.

Oh, and Tradone, if you want some REALLY long compiler errors, just start using templates. I had a compiler error for something or another that seriously dumped thousands of lines of crap... to this day, I don't know what it said the error was. [grin]
Shannon Barber
Shannon Barber
In C++ you can only define a static const integral value inline in a class.

struct CSSClass{	CSSClass(std::string a, std::string b, std::string c) : a(a), b(b), c(c) {}	std::string a; //not certain what these are called	std::string b;	std::string c;};struct CSSInstance{	CSSInstance(std::string a, std::string b, std::string c, std::string d ,std::string e, std::string f) : a(a), b(b), c(c), d(d), e(e), f(f) {}	std::string a; //these need better names as well	std::string b;	std::string c;	std::string d;	std::string e;	std::string f;};class Printer{public:	Printer();private:	std::vector<CSSClass>    css_classes;	std::vector<CSSInstance> css_instances;};Printer::Printer(){	css_classes.push_back(CSSClass("Table", "A",    "A:Hover"));	css_classes.push_back(CSSClass("Body",  "Link", "Hover"));	css_instances.push_back(CSSInstance("Decoration", "Color", "Bgcolor", "Face", "Size", "Style"));	css_instances.push_back(CSSInstance("text-decoration", "color", "background-color", "font-family", "font-size", "font-style"));}
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
smitty1276
smitty1276
Oh, Shannon, I just realized what you were saying... you were meaning to refer to static members. Yes those only work for integral types, I believe.

Note, however, that you still have to declare it again in the implementation.

class Foo {private:   const static int bar=5;};const int Foo::bar;


If you want another type you need to do this...

class Foo {private:   const static type bar;};const type Foo::bar = SOME_VALUE;  


I don't know if that will work for your string arrays or not though, off the top of my head.
Nitage
Nitage
Do you need to be able to change these values, or will they be const?

If they're const,static and private, you could move them to the anonymous namespace in the corresponding cpp file like this:

namespace{    const char* CSSClasses[2][3] = {			{"Table", "A", "A:Hover"},			{"Body", "Link", "Hover"} };        const char* CSSInstances[2][6] = {			{"Decoration", "Color", "Bgcolor", "Face", "Size", "Style"},			{"text-decoration", "color", "background-color", "font-family", "font-size", "font-style"};}


And just to clear it up, classes with user defined constructors (e.g. std::string) cannot be initialized in that fashion. That's why I used const char*s.

Quote:
Original post by smitty1276
Oh, Shannon, I just realized what you were saying... you were meaning to refer to static members. Yes those only work for integral types, I believe.

Note, however, that you still have to declare it again in the implementation.


No you don't.
Enigma
Enigma
Quote:
Original post by Nitage
No you don't.


It may have changed in the final Standard but according to the final draft Standard (and Scott Meyers in Effective C++ Item 1) you do:
Quote:
C++ Final Draft Standard, Section 9.4.2, Paragraph 4
If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions within its scope. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.

All my compilers however seem to allow you to elide the definition.

Σnigma
Sharlin
Sharlin
Quote:
Original post by Nitage
And just to clear it up, classes with user defined constructors (e.g. std::string) cannot be initialized in that fashion. That's why I used const char*s.


Yes they can; std::string has a non-explicit constructor taking a const char*. Anywhere you can use a const string instance, you can use a const char*.

The AP gave the "correct" solution if the strings don't have to be changed, and they can be shared between all the instances of the class. Quoted for emphasis:

Quote:
#include <string>class Print {   private:      const static std::string CSSClasses[2][3];   };// NOTE: the definition below has to be in a *single* place// that is, in a .cpp, not in a header.const std::string Print::CSSClasses[2][3] = {      {"Table", "A", "A:Hover"},      {"Body", "Link", "Hover"} };

Nitage
Nitage
Quote:
Original post by Enigma
Quote:
Original post by Nitage
No you don't.


It may have changed in the final Standard but according to the final draft Standard (and Scott Meyers in Effective C++ Item 1) you do:
Quote:
C++ Final Draft Standard, Section 9.4.2, Paragraph 4
If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that case, the member can appear in integral constant expressions within its scope. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.

All my compilers however seem to allow you to elide the definition.

Σnigma


See the standards committee site
I think this item covers this issue:
Quote:

454. When is a definition of a static data member required?


So it seems that until the next version of the standard is released, to be 100% compliant, you'd need to redefine the member.
DrEvil
DrEvil
My project is stuck with using gcc 2.95 for now, and it is true that static consts still have to be declared in the cpp, as smitty1276 mentioned. MSVC allows you to get away with not having it. Don't know if newer GCC versions do as well.
Tradone
Tradone
Quote:
Original post by smitty1276
Oh, and Tradone, if you want some REALLY long compiler errors, just start using templates. I had a compiler error for something or another that seriously dumped thousands of lines of crap... to this day, I don't know what it said the error was. [grin]


thanks, you made me not want to study C++ any further. lool
Tradone
Tradone
okay, there's way too many things going on here.
I'll try them out from the simpliest ones.
Thanks for your support.
i'll be sure to post the results.
Tradone
Tradone
Quote:
Original post by Anonymous Poster
Like this, maybe:

*** Source Snippet Removed ***


I'm going to go with the least sophisticated and it seemed to compile.
kool
Tradone
Tradone
Quote:
Original post by Nitage
Do you need to be able to change these values, or will they be const?

If they're const,static and private, you could move them to the anonymous namespace in the corresponding cpp file like this:

*** Source Snippet Removed ***

And just to clear it up, classes with user defined constructors (e.g. std::string) cannot be initialized in that fashion. That's why I used const char*s.

Quote:
Original post by smitty1276
Oh, Shannon, I just realized what you were saying... you were meaning to refer to static members. Yes those only work for integral types, I believe.

Note, however, that you still have to declare it again in the implementation.


No you don't.


actually the previous code didn't work.
i don't know why it compiled before guess I didn't upload the file just yet before compilation.
okay, so i'm gonna try this one next, this looks simply enough, but never really used namespaces before besides

using namespace std;

and I want to avoid global variables if possible... so..
Tradone
Tradone
what the hell?@#%
class Print {	private:		void PrintSoftwareInfo( std::string shenuVersion );		void PrintCSS( std::map< std::string, std::string > para_fieldData );		std::string shenuVersion;		struct		{			const static std::string Classes[2][3];			const static std::string Instances[2][6];		} CSS;..}//in cpp file		const static std::string Print::CSS.Classes[2][3] = {			{"Table", "A", "A:Hover"},			{"Body", "Link", "Hover"} };		const static std::string Print::CSS.Instances[2][6] = {			{"Decoration", "Color", "Bgcolor", "Face", "Size", "Style"},			{"text-decoration", "color", "background-color", "font-family", "font-size", "font-style"} };

errors:
Print.cpp:5: error: expected init-declarator before '.' token
Print.cpp:5: error: expected ,' or ;' before '.' token
Print.cpp:8: error: expected init-declarator before '.' token
Print.cpp:8: error: expected ,' or ;' before '.' token


I mean according to my logic this grammar should work.
hm... all that I've done was put it a structure.
what's wrong with C++, syntax is so complicated and I feel like in order to program things, I need to know how the compiler works.

I feel so dumb, I should read another book to make myself feel better.
Nitage
Nitage
Quote:
Original post by Tradone
what the hell?@#%
*** Source Snippet Removed ***
errors:
Print.cpp:5: error: expected init-declarator before '.' token
Print.cpp:5: error: expected ,' or ;' before '.' token
Print.cpp:8: error: expected init-declarator before '.' token
Print.cpp:8: error: expected ,' or ;' before '.' token


Replace
Print::CSS.Classes[2][3]
with
Print::CSS::Classes[2][3]
Tradone
Tradone
cool, this type of obfuscating grammar reminds me of back in grade school.
radius -> radii not radiuses

well, thanks. it compiled and i'm free again.
edit: no it did not compile.
//header file		struct		{			const static std::string Classes[2][3];			const static std::string Instances[2][6];		} CSS;//cpp file		const static std::string Print::CSS::Classes[2][3] = {			{"Table", "A", "A:Hover"},			{"Body", "Link", "Hover"} };		const static std::string Print::CSS::Instances[2][6] = {			{"Decoration", "Color", "Bgcolor", "Face", "Size", "Style"},			{"text-decoration", "color", "background-color", "font-family", "font-size", "font-style"} };

Print.cpp:5: error: class Print::CSS' is not a class or namespace
Print.cpp:8: error:
class Print::CSS' is not a class or namespace


hey i have another question...
is it quicker to make a declare a new variable on each and every method or reuse variables declared in the header?

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.