Maybe a simple C++ Question [crosspost]

I posted this over at AsyncLabs, but there is not much traffic over there… so for a bit more exposure, here it is again.

I have very little experience with C++, but I have an idea of what I want to do (so this could be impossible, or very simple for someone with more experience). I’ve looked all over, and I just can’t seem to find the keywords to tell me how to do what I want to do.

Here goes: I want to encapsulate a chunk of my code that does the tweeting for my project, and ideally I want the WiServer TWEETrequest as an object in my class, but I have no idea how to lay out the constructors to get it to compile.

Here is some very trimmed down example code:

#include <WiServer.h>

// Wireless configuration parameters ----------------------------------------
unsigned char local_ip[] = {10,0,10,170};   // IP address of WiShield
unsigned char gateway_ip[] = {10,0,10,1};   // router or gateway IP address
unsigned char subnet_mask[] = {255,255,255,0};   // subnet mask for the local network
const prog_char ssid[] PROGMEM = {"MySSID"};      // max 32 bytes

unsigned char security_type = 2;   // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = {"WPAPASS1010"};   // max 64 characters

// WEP 128-bit keys
// sample HEX keys
prog_uchar wep_keys[] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,   // Key 0
              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // Key 1
              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // Key 2
              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00   // Key 3
            };

// setup the wireless mode
// infrastructure - connect to AP
// adhoc - connect to another WiFi device
unsigned char wireless_mode = WIRELESS_MODE_INFRA;

unsigned char ssid_len;
unsigned char security_passphrase_len;
// End of wireless configuration parameters ----------------------------------------


class genericClass
{
  public:
    genericClass();

    void doTweet( unsigned int mode );

  private:
    void _genericTweeter();
    char* _auth;
    
    unsigned int _mode;
    
//   TWEETrequest _TweetPeriodic;
   TWEETrequest _TweetPeriodicDontWork( char* , void* );
  
};

genericClass::genericClass()
{
  _auth = "mDyEaAuDtBhEeF===";
  _TweetPeriodicDontWork = new TWEETrequest(_auth, _genericTweeter); // The Problem, apparently...
}

void genericClass::doTweet( unsigned int mode )
{
   _mode = mode; 
  _TweetPeriodicDontWork.submit();
}

void genericClass::_genericTweeter()
{
switch( _mode )
{
   case 1:
      WiServer.print("Tweet Mode 1");
    break;
   
   case 0:
  default:
      WiServer.print("Tweet Mode 0 (default)");
     break;
} 
  
}


genericClass myClass;

void setup()
{
  WiServer.init(NULL);
  WiServer.enableVerboseMode(true);
}

void loop()
{
  int somelogic;
  
  if( somelogic )
    myClass.doTweet(1);
  else
    myClass.doTweet(0);
    
  
  WiServer.server_task();  
    
  delay(100);  
}

My gut tells me that I need to fire off a TWEETrequest constructor in my class constructor, but I’m failing at the syntax in the AVR environment.

Any help would be great, thanks.

You do need a constructor. However you can't put the class definition and implementation in a .pde file.

The class definition needs to go in a .h file. The class implementation needs to go in a .cpp file that includes the .h file.

The sketch also needs to include the .h file, to get the .cpp file compiled.

However, from looking at your class, it appears to be just a container for a few methods. What does creating a class bring to the party?

This is purely a piece of example code to try to get an answer of how to fire off the constructor for the sub-object (is that the right word for it).

I've had no problem putting the class definition and the class methods in the main PDE file, and for the purposes of this example the code compiles fine if I comment out the references to TWEETrequest. I'm not making a distributable library...

And as I said, this is purely example code. The real project I am working with has valid reasons for packaging up into a class.

Is this what you try to do: ?

class ClassWithConstructor {
public:
  ClassWithConstructor(int i) {/*do nothing*/}
};

class ClassThatWrapsOtherClass {
public:
  ClassThatWrapsOtherClass(int i) : cwc(2) {/*do nothing*/}
private:
  ClassWithConstructor cwc;
};

ClassWithConstructor shows how to

fire off the constructor for the sub-object

:) [edit]Fixed as per PaulS' observation. Thanks :)[/edit]

  ClassWithConstructor(int i) : cwc(2) {/*do nothing*/}

Shouldn't this be:

  ClassThatWrapsOtherClass(int i) : cwc(2) {/*do nothing*/}
class A
{
  public:
    A( int ArgA, int ArgB );
};

class B
{
  public:
    B( );  // No arguments

  private:
    
    int Aarg1;
    int Aarg2;
    
    A clsA1( Aarg1, Aarg2 );  // Arduino Complier will barf on this...
    A clsA2( int, int);  // but not on this

}

B:B()
{

  [do other stuff, such as setting Aarg1 and Aarg2]

  // How to construct A???
}

I don't want to overload or inherit the functions of the other class, I just want to know how to construct it in my own class.

So an even more trimmed down example above: Class A requires two arguments to it's constructor. You can't put the arguments in the Class Descriptor, because the compiler wants types there. But as soon as I try to create an object B, it complains that there is no constructor for object A.

I can't try out your suggestion at the moment (at work), but I'm not sure if it is what I am getting at...

So, why not have an Init method in class A that does everything that the constructor would normally do. Then, after instantiating B, call the Init method on the A objects.

B myB; myB.clsA1.Init(//Whatever); myB.clsA2.Init(//Whatever);

Well, Class A is in a library, and I can't modify it (or I would rather not modify it and then submit the changes back to the people that wrote it).

It looks like I'm going to have to put my even more simple example into the IDE and start copying the error messages out, because I guess I'm not conveying the issues properly. I'll do that tonight.

Ok, let's break this down and be more explicit about what I want to do...

Here is a fully-operational sample sketch. Let's say class "A" is from a library, and I can't easily change it. Class B is my class that I want to do something with.

//--------------------------------------------------
// Class A Library Function - Not easily modified
//--------------------------------------------------
class A
{
 public:
   A( int Arg1, int Arg2);
  
};

A::A( int Arg1, int Arg2)
{
  Serial.print("Class A Constructed! ");
  Serial.print(Arg1); Serial.print(" ");
  Serial.println(Arg2); 
}

//--------------------------------------------------
// Class B - My class
//--------------------------------------------------
class B
{
 public:
   B( char Chr1 );
   
 private:
  int _Aarg1;
  int _Aarg2;
  
  
  
};

B::B( char Chr1 )
{
  Serial.print("Class B Constructed! ");
  Serial.println(Chr1);

  _Aarg1 = (int)Chr1 - 0x30;
  _Aarg2 = (int)Chr1 - 0x30;
}


//--------------------------------------------------
// Basics
//--------------------------------------------------
void setup(){Serial.begin(9600);}

void loop()
{
  A standaloneA( 1, 2 );

  B arrayOfBs[2] =
  {
    B('x'),
    B('z') 
  };


  Serial.println("tic ");
  delay(10000);  
}

As expected, this compiles and burns to the board just fine, the output as expected:

Class A Constructed! 1 2 Class B Constructed! x Class B Constructed! z tic

NOW, I'd like to have a PRIVATE instance of Class A in class B.

First I thought I'd just make an empty declaration:

//--------------------------------------------------
// Class A Library Function - Not easily modified
//--------------------------------------------------
class A
{
 public:
   A( int Arg1, int Arg2);
  
};

A::A( int Arg1, int Arg2)
{
  Serial.print("Class A Constructed! ");
  Serial.print(Arg1); Serial.print(" ");
  Serial.println(Arg2); 
}

//--------------------------------------------------
// Class B - My class
//--------------------------------------------------
class B
{
 public:
   B( char Chr1 );
   
 private:
  int _Aarg1;
  int _Aarg2;
  
  [glow]A NoMatchtingFunctionCall;[/glow]
  
};

B::B( char Chr1 )
{
  Serial.print("Class B Constructed! ");
  Serial.println(Chr1);

  _Aarg1 = (int)Chr1 - 0x30;
  _Aarg2 = (int)Chr1 - 0x30;

}


//--------------------------------------------------
// Basics
//--------------------------------------------------
void setup(){Serial.begin(9600);}

void loop()
{
  A standaloneA( 1, 2 );

  B arrayOfBs[2] =
  {
    B('x'),
    B('z') 
  };


  Serial.println("tic ");
  delay(10000);  
}

The compiler returns:

In constructor 'B::B(char)': error: no matching function for call to 'A::A()

So, I tried calling it like I had before...

//--------------------------------------------------
// Class A Library Function - Not easily modified
//--------------------------------------------------
class A
{
 public:
   A( int Arg1, int Arg2);
  
};

A::A( int Arg1, int Arg2)
{
  Serial.print("Class A Constructed! ");
  Serial.print(Arg1); Serial.print(" ");
  Serial.println(Arg2); 
}

//--------------------------------------------------
// Class B - My class
//--------------------------------------------------
class B
{
 public:
   B( char Chr1 );
   
 private:
  int _Aarg1;
  int _Aarg2;
  
 [glow]A NotAType( _Aarg1, _Aarg2 );[/glow]
  
};

B::B( char Chr1 )
{
  Serial.print("Class B Constructed! ");
  Serial.println(Chr1);

  _Aarg1 = (int)Chr1 - 0x30;
  _Aarg2 = (int)Chr1 - 0x30;
  
}


//--------------------------------------------------
// Basics
//--------------------------------------------------
void setup(){Serial.begin(9600);}

void loop()
{
  A standaloneA( 1, 2 );

  B arrayOfBs[2] =
  {
    B('x'),
    B('z') 
  };


  Serial.println("tic ");
  delay(10000);  
}

That returns:

error: '_Aarg1' is not a type

Ok, that makes sense, because that's the class description, no code has been executed at this point. So I change it to the prototype for the constructor, but now HOW do I construct the A class once B gets constructed:

//--------------------------------------------------
// Class A Library Function - Not easily modified
//--------------------------------------------------
class A
{
 public:
   A( int Arg1, int Arg2);
  
};

A::A( int Arg1, int Arg2)
{
  Serial.print("Class A Constructed! ");
  Serial.print(Arg1); Serial.print(" ");
  Serial.println(Arg2);
}

//--------------------------------------------------
// Class B - My class
//--------------------------------------------------
class B
{
 public:
   B( char Chr1 );
  
 private:
  int _Aarg1;
  int _Aarg2;
  
[glow]    A subclassA( int, int );  // Compiler thinks this is OK,
                        // but it still has not been
                        // constructed.[/glow]
  
};

B::B( char Chr1 )
{
  Serial.print("Class B Constructed! ");
  Serial.println(Chr1);

  _Aarg1 = (int)Chr1 - 0x30;
  _Aarg2 = (int)Chr1 - 0x30;
  
[glow]  subclassA = new A( _Aarg1, _Aarg2 ); // THIS is what
                               // I am asking...
                               // How do I create
                               // this instance??[/glow]
}


//--------------------------------------------------
// Basics
//--------------------------------------------------
void setup(){Serial.begin(9600);}

void loop()
{
  A standaloneA( 1, 2 );

  B arrayOfBs[2] =
  {
    B('x'),
    B('z')
  };


  Serial.println("tic ");
  delay(10000);  
}

This returns:

In constructor 'B::B(char)': error: invalid use of member (did you forget the '&' ?)

And that's where I'm at. It seems that I'm not calling the constructor properly.

I have a feeling this could just be a pointer/reference issue, but all I am asking is the proper code to fire off the constructor for A within the constructor for B. I don't want B to inherit from A if I don't have to, besides, what if I had an array of A's in B?

I know this is probably something pretty basic for C++ gurus out there... I was hoping I was just missing something simple.

Try this…

class B
{
 public:
   B( char Chr1 );
 private:
   A subclassA;
};

B::B( char Chr1 )
  : subclassA( (int)Chr1 - 0x30, (int)Chr1 - 0x30 )
{
}
B::B( char Chr1 )
  : subclassA( _Aarg1, _Aarg2 )
{
  Serial.print("Class B Constructed! ");
  Serial.println(Chr1);

  _Aarg1 = (int)Chr1 - 0x30;
  _Aarg2 = (int)Chr1 - 0x30;
  
//  subclassA = new A( _Aarg1, _Aarg2 ); // THIS is what
                               // I am asking...
                               // How do I create
                               // this instance??
}

In constructor 'B::B(char)': error: class 'B' does not have any field named 'subclassA

These are working sketches. Copying and pasting them into your Arduino 0017 would give you the same error.

//--------------------------------------------------
// Class A Library Function - Not easily modified
//--------------------------------------------------
class A
{
 public:
   A( int Arg1, int Arg2);
  
};

A::A( int Arg1, int Arg2)
{
  Serial.print("Class A Constructed! ");
  Serial.print(Arg1); Serial.print(" ");
  Serial.println(Arg2);
}

//--------------------------------------------------
// Class B - My class
//--------------------------------------------------
class B
{
 public:
   B( char Chr1 );
  
 private:
  int _Aarg1;
  int _Aarg2;
  
[glow]    A subclassA( int, int );  // Compiler thinks this is OK,
                        // but it still has not been
                        // constructed.
  

    A otherclassA( int, int ); // some other one, entirely[/glow]

};

B::B( char Chr1 )
{
  Serial.print("Class B Constructed! ");
  Serial.println(Chr1);

  _Aarg1 = (int)Chr1 - 0x30; // These may not be dependent
  _Aarg2 = (int)Chr1 - 0x30; //   on B's arguments.
  
[glow]  subclassA = new A( _Aarg1, _Aarg2 ); // THIS is what
                               // I am asking...
                               // How do I create
                               // this instance??

  otherclassA = new A( _Aarg2, _Aarg1 ); // THIS is what
                               // I am asking...
                               // How do I create
                               // this instance??[/glow]
}


//--------------------------------------------------
// Basics
//--------------------------------------------------
void setup(){Serial.begin(9600);}

void loop()
{
  A standaloneA( 1, 2 );

  B arrayOfBs[2] =
  {
    B('x'),
    B('z')
  };


  Serial.println("tic ");
  delay(10000);  
}

What if there were an ARRAY of A's? Another question is if there was another object 'C' that took arguments in its constructor as well.

It seems that most of the suggestions that I have been getting have been (to use the car analogy) how to inherit a Vehicle Class to make a Car Class or a Truck Class, when I am trying to make a Road Class that contains vehicles. I don't know if that helps any more...

It seems that most of the suggestions that I have been getting have been (to use the car analogy) how to inherit a Vehicle Class to make a Car Class or a Truck Class, when I am trying to make a Road Class that contains vehicles. I don't know if that helps any more...

But, using your analogy, you are trying to create the road with all the vehicles. If you created the road, and then added vehicles to it, you would not be having this problem.

But, using your analogy, you are trying to create the road with all the vehicles. If you created the road, and then added vehicles to it, you would not be having this problem.

Ok, that's getting more to the heart of what I am asking (as you can tell I don't have the vocabulary on the subject to ask the right questions.

I don't know how to create those instances, and that is what I am asking.

//--------------------------------------------------
// Class A Library Function - Not easily modified
//--------------------------------------------------
class A
{
 public:
   A( int Arg1, int Arg2);

};

A::A( int Arg1, int Arg2)
{
  Serial.print("Class A Constructed! ");
  Serial.print(Arg1); Serial.print(" ");
  Serial.println(Arg2);
}

//--------------------------------------------------
// Class B - My class
//--------------------------------------------------
class B
{
 public:
   B( char Chr1 );
   [glow]initClassA();[/glow]

 private:
  int _Aarg1;
  int _Aarg2;

    A subclassA( int, int );  // Compiler thinks this is OK,
                        // but it still has not been
                        // constructed.

};

B::B( char Chr1 )
{
  Serial.print("Class B Constructed! ");
  Serial.println(Chr1);

  _Aarg1 = (int)Chr1 - 0x30; // These may not be dependent
  _Aarg2 = (int)Chr1 - 0x30; //   on B's arguments.

}

[glow]B::initClassA()
{

  subclassA = new A( _Aarg1, _Aarg2 ); // THIS is what
                               // I am asking...
                               // How do I create
                               // this instance??

}[/glow]


//--------------------------------------------------
// Basics
//--------------------------------------------------
void setup(){Serial.begin(9600);}

void loop()
{
  A standaloneA( 1, 2 );

  B arrayOfBs[2] =
  {
    B('x'),
    B('z')
  };

[glow]  arrayOfBs[0].initClassA();
  arrayOfBs[1].initClassA();[/glow]


  Serial.println("tic ");
  delay(10000);
}

I know the syntax is wrong in THIS LINE. How do I fix it?

subclassA = new A( _Aarg1, _Aarg2 );

If you can live with creating the cars 'outside' the road you'll be fine.

You can use pointers for this.

If you take your time and explain what you want to do in detail, with representative code, I'll gladly help you.

If you can live with creating the cars ‘outside’ the road you’ll be fine.

You can use pointers for this.

I know how to do that, and that’s pretty much how my code is set up now. I was just looking to encapsulate things a bit more and simplify the use of the library that I am writing.

If you take your time and explain what you want to do in detail, with representative code, I’ll gladly help you.

I thought I did that with the code in my original post.

I have a system that I am setting up that takes in sensor inputs, process them, displays them to an LCD, and also has an Internet interface. The net interface is AsyncLabs WiServer, and currently only uses their Twitter interface (it was the easiest thing to do at first), but it will expand to have a WebServer so that I can pull info out to a more rich web interface.

Right now I have the system working, but I don’t like how the code is organized, and I want to eventually make a single library that has all of the code for this project with a simple “API”. This includes pulling all of the internet access methods into a class and wraping them with a simple interface.

As you can see in my original post, the TWEETrequest (Class A in my simple example) object takes two arguments that I want to tie into private variables in the class that contains it (_Aarg1 and _Aarg2 in my simple example). Ideally this would be private as well (for my API purposes).

The constructor for my NetAccess class (genericClass in my first example) will likely not have anything to do (from an external standpoint) for setting up the TWEETrequest class (or any of the other Web Interface classes that are provided by WiServer which I plan to encapsulate in this class as well).

The first example I posted is exactly what I am trying to do, but trimmed down to just the code that I am asking about, and names changed to protect the innocent.

This code is as much as a C++ learning experience for me as anything else, and I’m not looking for a code review of “why” I am doing something (yet), right now I am just asking “how” to do something.

So, the (not so) simple question remains: how to I create a private instance of another object within a class so that it gets constructed when the main class gets constructed OR when another initializer function is called.

how to I create a private instance of another object within a class so that it gets constructed when the main class gets constructed

Here:

class A {
public:
      A(int param) {}
};

class B {
public:
      B(int param) : a(param) {}
private:
      A a;
};

void setup() {
      B b(3);
}

void loop() {}

:)

Ok. Now what if the parameters for 'a' had nothing to do with the parameters for b?

class A {
public:
      A(int param) {}
};

class B {
public:
      B(int param) : a([glow]_As_arg[/glow]) 
                { [glow]complexLogicThatCalculates_As_arg[/glow] }
private:
      [glow]int _As_arg;[/glow]
      A a;
};

void setup() {
      B b(3);
}

void loop() {}

and to expand on my question... what if there is an array of As?

class A {
public:
      A(int param) {}
};

class B {
public:
      B(int param) : a(param) {}  [glow]// ???[/glow]
private:
      [glow]A arrOfA[10];[/glow]
};

void setup() {
      B b(3);
}

void loop() {}

or if there is another class "C"

class A {
public:
      A(int param) {}
};

[glow]class C {
public:
      C(int p1, int p2, int p3) {}
};[/glow]

class B {
public:
      B(int param) : a(param) {}  [glow]// ???[/glow]
private:
      A a;
      [glow]C c;[/glow]
};

void setup() {
      B b(3);
}

void loop() {}

Sorry if I seem slow about this, but I cannot seem to find any resources that will show me, in general, how the syntax works for this language. :-[

Are you sure you need to use libraries? [if not, let us know :)]

Are you going to have many 'roads'? [if not, let us know :)]

[if both answers was 'yes' read:] If you want to use arrays, you need an empty constructor, and a construct/begin function for deferred construction of the library. This is often called two-phase construction.

I guess you guys are hammering home the “Don’t Do That” point.

That’s a good link, and is good reference for me. Even IF I wanted to do that, I still don’t have the syntax right to use the ‘new’ operator in the context of my project (which I guess I wanted to know all along, but as you guys have said “Don’t Do That”).

Maybe it’s time to audit a C++ class at the community college.

I thought the parts of your code that had the new operator had it because it was a bi product of what you tried to do. If your question was about the new operator, you could've asked about it ;) And, I do not mean that as abrupt as it looks.

There is no implementation of the new operator in Arduinoworld A google search on arduino + new + operator should give you some leads on how to implement it yourself.

If I'm hammering a point I think it would have to be something like: "Don't do that like you want it, but like it should be done". And again, no pun intended :)

/me apparently has trouble with formulating polite english sentences :-[