class initialized array

G

Gary Wessle

Hi

how can I initialize a const char* myarr[] in a class constructor?

class Myclass {
const char* myarr[] = { "abc", "def" };
....
};


Myclass::Myclass():
myarr[]( ??? )
{}

thanks
 
X

XtremDev

You need to add the static keyword.

class MyClass
{
public:

MyClass(){}
~MyClass(){}

static const char * myarr[];
};

const char * MyClass::myarr[] = {"abc", "def" };
 
M

mlimber

Gary said:
how can I initialize a const char* myarr[] in a class constructor?

class Myclass {
const char* myarr[] = { "abc", "def" };
...
};


Myclass::Myclass():
myarr[]( ??? )
{}

Use a vector of strings rather than an array of char pointers
(http://www.parashift.com/c++-faq-lite/containers.html#faq-34.1), and
then use an initializer helper class:

template<typename T>
class Initializer
{
vector<T> v_;
public:
Initializer( size_t reserveSize=0 ) { v_.reserve( reserveSize ); }
Initializer& Add( const T& t ) { v_.push_back(t); return *this; }
operator vector<T>() const { return v_; }
};

class Myclass {
const vector<string> myarr;
public:
Myclass()
: myarr( Initializer( 2 )
.Add( "abc" )
.Add( "def" ) )
{}
};

Cheers! --M
 
M

mlimber

XtremDev said:
You need to add the static keyword.

class MyClass
{
public:

MyClass(){}
~MyClass(){}

static const char * myarr[];
};

const char * MyClass::myarr[] = {"abc", "def" };

What if it's not static data?

Cheers! --M
 
A

Andrey Tarasevich

Gary said:
...
how can I initialize a const char* myarr[] in a class constructor?

class Myclass {
const char* myarr[] = { "abc", "def" };
...
};


Myclass::Myclass():
myarr[]( ??? )
{}
...

In this context arrays support only one initializer syntax: '()'-initializer,
which leads to zero-initialization.

In your case one way around is to declare the array with explicitly specified size

class Myclass {
const char* myarr[2];
...
};

and use assignment instead of initialization

Myclass::Myclass()
{
myarr[0] = "abc";
myarr[1] = "def";
}
 
M

mlimber

Andrey said:
Gary said:
...
how can I initialize a const char* myarr[] in a class constructor?

class Myclass {
const char* myarr[] = { "abc", "def" };
...
};


Myclass::Myclass():
myarr[]( ??? )
{}
...

In this context arrays support only one initializer syntax: '()'-initializer,
which leads to zero-initialization.

In your case one way around is to declare the array with explicitly specified size

class Myclass {
const char* myarr[2];
...
};

and use assignment instead of initialization

Myclass::Myclass()
{
myarr[0] = "abc";
myarr[1] = "def";
}

Right, although probably the pointers should almost certainly be const
also
(http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.1),
which would eliminate this possibility.

Cheers! --M
 
A

Andrey Tarasevich

mlimber said:
...
and use assignment instead of initialization

Myclass::Myclass()
{
myarr[0] = "abc";
myarr[1] = "def";
}

Right, although probably the pointers should almost certainly be const
also
...

That's something only the OP knows.
 
S

Salt_Peter

Gary said:
Hi

how can I initialize a const char* myarr[] in a class constructor?

class Myclass {
const char* myarr[] = { "abc", "def" };
...
};


Myclass::Myclass():
myarr[]( ??? )
{}

thanks

You could deal with allocating a pointer in the ctor body.
But thats old school stuff and frankly: much more work and way too
fragile.
You can only initialize an array with default values.
example:

template< typename T, const size_t Size >
MyClass
{
T array[ Size ];
MyClass() : array() { } // init elements to
// whatever the default T() might be
};

A std::string doesn't suffer from that handicap.

#include <iostream>
#include <ostream>
#include <string>

template < typename T >
class MyClass
{
T m_t;
public:
MyClass(const T& t) : m_t(t) { }
friend
std::eek:stream&
operator<<(std::eek:stream& os, const MyClass& r_my)
{
return os << r_my.m_t;
}
};

int main()
{
MyClass< std::string > instance("abc def");
std::cout << instance << std::endl; // so simple

return 0;
}
 
S

Salt_Peter

XtremDev said:
You need to add the static keyword.

class MyClass
{
public:

MyClass(){}
~MyClass(){}

static const char * myarr[];
};

const char * MyClass::myarr[] = {"abc", "def" };

Static members are nearly never a "better" solution or even a solution
at all.
Specially when static members is not what is required.
In this case, you have no choice but to provide static member functions
to access the static member.
Then there is the real showstopper for those of you that enjoy living
in a static world:
What's the "static initialization order fiasco"?
http://www.parashift.com/c++-faq-lite/ctors.html
section 10.12

The better solution in this case is std::strings or std::vector of
strings.
 
A

Andrey Tarasevich

Salt_Peter said:
You need to add the static keyword.

class MyClass
{
public:

MyClass(){}
~MyClass(){}

static const char * myarr[];
};

const char * MyClass::myarr[] = {"abc", "def" };

Static members are nearly never a "better" solution or even a solution
at all.

If the data in 'myarr' is not [potentially] specific to each instance of the
class, then 'static' is not only a solution, but the best solution possible.
Actually, it would be a design error not to use 'static' in that case.
Specially when static members is not what is required.

That is the question only OP can answer.
In this case, you have no choice but to provide static member functions
to access the static member.

Not necessarily. If depends heavily on what is the purpose of that member and
how it is supposed to be used. That's another question only OP can answer.
Then there is the real showstopper for those of you that enjoy living
in a static world:
What's the "static initialization order fiasco"?
http://www.parashift.com/c++-faq-lite/ctors.html
section 10.12

That's a far cry from what we have in the OP's case. Almost unrelated. It's like
saying "Don't use dynamic memory to store arrays of 'int's because one day
you'll forget to declare some class's destructor as 'virtual'".
The better solution in this case is std::strings or std::vector of
strings.

It depends on "what is required".
 
B

BobR

Salt_Peter wrote in message ...
You need to add the static keyword.

class MyClass { public:
MyClass(){}
~MyClass(){}
static const char * myarr[];
};
const char * MyClass::myarr[] = {"abc", "def" };


In this case, you have no choice but to provide static member functions
to access the static member.

Is that statement backwards, or, is my compiler deprecated?
'print()' is non-static, but, prints the (static) lines.

class Examp{ public:
Examp( int const n ) : index( n ){}
Examp() : index( 0 ){}
// ----------------------
void print( std::eek:stream &out ) const {
if( index < 0 || index > MaxLines - 1 ){
out << lines[ 0 ];
}
else{
out << lines[ index ];
}
return;
} // print()
//----------------------
private:
int index;
static int const MaxLines = 4;
static std::string const lines[ MaxLines ];
}; //end class Examp
// ------------------------------------
// -- static --
std::string const Examp::lines[ Examp::MaxLines ] = {
"String 1.\n",
"String 2.\n",
"String 3.\n",
"ERROR in indexing.\n"
};
// ------------------------------------

int main(){
Examp X(1);
X.print( std::cout );
}
 
S

Salt_Peter

BobR said:
Salt_Peter wrote in message ...
You need to add the static keyword.

class MyClass { public:
MyClass(){}
~MyClass(){}
static const char * myarr[];
};
const char * MyClass::myarr[] = {"abc", "def" };


In this case, you have no choice but to provide static member functions
to access the static member.

Is that statement backwards, or, is my compiler deprecated?
'print()' is non-static, but, prints the (static) lines.

print() is const, static if you prefer
class Examp{ public:
Examp( int const n ) : index( n ){}
Examp() : index( 0 ){}
// ----------------------
void print( std::eek:stream &out ) const {
if( index < 0 || index > MaxLines - 1 ){
out << lines[ 0 ];
}
else{
out << lines[ index ];
}
return;
} // print()
//----------------------
private:
int index;
static int const MaxLines = 4;
static std::string const lines[ MaxLines ];
}; //end class Examp
// ------------------------------------
// -- static --
std::string const Examp::lines[ Examp::MaxLines ] = {
"String 1.\n",
"String 2.\n",
"String 3.\n",
"ERROR in indexing.\n"
};
// ------------------------------------

int main(){
Examp X(1);
X.print( std::cout );
}

Why not...

#include <iostream>
#include <ostream>
#include <vector>
#include <string>
#include <iterator>

class Examp
{
std::vector< std::string > vs;
public:
Examp() : vs() { load(); }
void load();
/* friend */
friend std::eek:stream&
operator<<( std::eek:stream&, const Examp& );
};

void Examp::load()
{
vs.push_back( "String 0." );
vs.push_back( "String 1." );
vs.push_back( "String 2." );
}

std::eek:stream&
operator<<( std::eek:stream& os, const Examp& r_x )
{
std::copy( r_x.vs.begin(),
r_x.vs.end(),
std::eek:stream_iterator
< std::string >( os, "\n" ) );
return os;
}

int main()
{
Examp examp;
std::cout << examp;
}

It doesn't get any simpler.
And you can make examp static for all i care.
 
B

BobR

Salt_Peter wrote in message
print() is const, static if you prefer

So? Remove the 'const', it still compiles and runs for me. What I was getting
around to is, AFAIK, a non-static function can access static members, but, a
static function can only access static data members and static functions.
More below......
class Examp{ public:
Examp( int const n ) : index( n ){}
Examp() : index( 0 ){}
// ----------------------
void print( std::eek:stream &out ) const {
if( index < 0 || index > MaxLines - 1 ){
out << lines[ 0 ];
}
else{ out << lines[ index ]; }
return;
} // print()
//----------------------
private:
int index;
static int const MaxLines = 4;
static std::string const lines[ MaxLines ];
}; //end class Examp
// ------------------------------------
// -- static --
std::string const Examp::lines[ Examp::MaxLines ] = {
"String 1.\n", "String 2.\n", "String 3.\n",
"ERROR in indexing.\n"
};
// ------------------------------------

int main(){
Examp X(1);
X.print( std::cout );
}

Bob R POVrookie

Why not...

#include <iostream>
#include <ostream>
#include <vector>
#include <string>
#include <iterator>

class Examp {
std::vector< std::string > vs;
public:
Examp() : vs() { load(); }
void load();
/* friend */
friend std::eek:stream&
operator<<( std::eek:stream&, const Examp& );
};

void Examp::load(){
vs.push_back( "String 0." );
vs.push_back( "String 1." );
vs.push_back( "String 2." );
}

std::eek:stream&
operator<<( std::eek:stream& os, const Examp& r_x ){
std::copy( r_x.vs.begin(), r_x.vs.end(),
std::eek:stream_iterator< std::string >( os, "\n" ) );
return os;
}

int main(){
Examp examp;
std::cout << examp;
}

It doesn't get any simpler.
And you can make examp static for all i care.

In my class, no matter how many objects of the class there are, those strings
are never duplicated, there's just that one piece of storage. Remove the
'const' on the strings and you could change them. Put them in 'public:' and
you don't even need an instance of the class to access them (like: a global
with a scope resolution operator / namespace).

If you wanted different strings in each instance, your class would be the way
to go.

It comes down to how you want to use the class / data.

Oh, almost forgot: My class is better than your class 'cause it uses two less
header includes. <G>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,539
Members
45,024
Latest member
ARDU_PROgrammER

Latest Threads

Top