mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

If you want to avoid a lot of repetition and "magic numbers" in your code, you might want to think about computing the 'first', 'second', .. variables in terms of ROW and COL. You also might want to think about not duplicating code that prints the same pattern (like your example pattern has two repeated patterns (lower triangle, upper triangle, lower triangle, upper triangle). A hint is to use the integer modulus operator % and the integer division /.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>Since small object allocation in heap is bad

From the perspective of experience, allocating anything from heap memory is bad, whatever size it has. You only do it when it is required. It is required when the size or type is not known at compile-time, or if it's too big to be on the stack.

When it comes to "small objects", we usually mean built-in types (like int, double, etc.) and objects that aren't much bigger than a few times the size of the native word size (i.e. size of an int or a pointer). But, usually, all POD-types (Plain Old Data types) are rarely allocated individually on the heap (not in an array), because they are rarely very big (too big for the stack), their size is known at compile-time (since there is just one), and their type is known at compile-time (i.e. POD-types are not, by definition, part of an inheritance scheme). There are a few exceptions (like shared objects), but they get almost always allocated statically (not on heap).

Finally, C++ has all the containers required to handle variable-size "arrays" in any way you like. And they are optimized to minimize heap allocations.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>I don't know the major differences apart from headers and inputs and outputs should be replaced with cout << and cin >>

Well. That's actually all you need to change to turn the code into C++ code.

#include <iostream>  //this replaces stdio.h

const int ROW = 4;
const int COL = 13;

int main(void) {
   int max = COL;
   
   for(int i = 0;i<ROW;i++) { //in C++, it is preferred to declare loop variables in the for-statement.
      for(int c=0;c<COL;c++) {
         if(c == i+1 || c == 6 || c == max-2)
            std::cout << ' ';  //output is done through std::cout.
         else   
            std::cout << '*';
      }
      --max;
      std::cout << std::endl;  //std::endl is used for new-line (instead of '\n').
   }
   return 0;
}
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>will this work?

Just try it:

void foo(int bar[], int sz) {
  for(int i = 0; i < sz; ++i) 
    bar[i] = 42;
};

int main() {
  int b[50];
  foo(b,50);
  return 0;
};

and yes, it works.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>As you've mentioned "avoiding memory problems by design", perhaps I could do a proof read of the tutorial if that suits you?

I finished the tutorial now, and you can read it here if still interested.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

An lvalue is defined as something that can appear on the left-hand-side of an assignment (like a = b; ). Basically, it needs to be a variable with a name, i.e., not a temporary or constant value (like 5 ). Certain operations, like the assignment operator, require that the variable you use it with be an lvalue, and thus, the error "lvalue required". The other kind of variables, called rvalues (which can appear only in the right-hand-side of an assignment), cannot be converted to lvalues, so if you feed an rvalue to a function or operation that requires an lvalue, you get the "lvalue required" error.

Post the code that is giving you trouble and then we can give more concrete help.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Beginner's guide to C++0x:
Avoiding Memory Problems by Design of Ownership

If you ever read any resources on C++ programming or object-oriented programming, you must have heard some rethorics like "inheritance is for the is a relation, composition is for the has a relation". Is that all? Is that the end of the story? What is the underlying motivation for this dichotomy? What if my case fits neither category?

The point of this tutorial is to answer those questions and show how to translate the answers into real C++0x code. This tutorial is really about thinking about the relationships between the objects that constitute a software.

We can already answer the first question: Is that all? No. Programming tasks are rarely simple, and applications of object-oriented programming are no exception, meaning that relationships between objects can be complex, and so, no, the "is a" and "has a" dichotomy is not all there is to object-oriented design.

If you have read the title of this tutorial, you have also read the answer to the second question: What is the underlying motivation for this dichotomy? Ownership. The "is a" and "has a" dichotomy is really there to separate what specializes what and what owns what. Off the bat, of course, even these broad relations are not enough, it's missing the "unrelated" relation. In some sense, there are three poles, i.e. no-relation, specialization and ownership, that bound the continuum of possible relations between objects in a software. Needless …

alwaysLearning0 commented: nice +5
kvprajapati commented: Many thanks! awesome :) +15
Ancient Dragon commented: Excellent :) +14
Labdabeta commented: Bookmarked reference page now! +6
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

X3D also has a binary version already, called x3db.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Blender is a pretty good editor and it supports many formats.

The world of 3D file-formats is seriously lacking a wide-spread standard format. It used to be 3ds, when only 3D Studio Max existed as a decent editor. Now, there are many 3D editors, many formats, and most game-studios have in-house formats too.

For the kind of thing you are looking for, you might want to use X3D. It also has some open-source libs to manipulate them, but since it is an XML format, you can also just use a generic xml library.

Ketsuekiame commented: Totally forgot about X3D as we use in-house formats ^^ +8
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Post your code between the code tags [_CODE_] [_/_CODE_] (with no underscores).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The OpenCV library can do this easily. It might be a bit of overkill since OpenCV is a lot more feature-rich than you need.

Another alternative and very easy to use library is FreeImage.

Also, if you have access to linux, either on your computer or your website's server machine, you can solve your problem very easily with a simple shell script that calls the "convert" linux-command. For example, these simple commands would work:

$ cp src_dir/*.jpg dest_dir/
$ convert -size 80x80 dest_dir/*.jpg -resize 80x80
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

As said, the new C++ standard solves your implementation problem with the new feature of variadic templates. However, there is also a solution that solves the problem you made your class for. The library called Boost.Bind (which is also now part of the new standard) was made for that purpose, and, since it is C++98 compliant, it does actually hide, under-the-hood, a series of overloads for all the different numbers of parameters (up to 10).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The standard class for this purpose is std::numeric_limits, in the <limits> header.

You can basically use it in this way:

template <typename T>
T getMaximumValue() {
  if( std::numeric_limits<T>::has_infinity() )
    return std::numeric_limits<T>::infinity();
  else
    return std::numeric_limits<T>::max();
};

So, if you are using the "double" type for example, you could do:

double getMaximumDouble() {
  if( std::numeric_limits<double>::has_infinity() )
    return std::numeric_limits<double>::infinity();
  else
    return std::numeric_limits<double>::max();
};
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>I did not.The default template argument should have been deduced when initializing 'str' so there wasn't a need for providing it.

Then, you should have put:

//This is the definition of the str member of the template specialization of asd for its default template-parameter:
template <>
const char* asd<>::str = "asd";

//This is the definition of a "str" template-member for the template specialization of asd for its default template-parameter (which is illegal):
template <const char*>
const char* asd<>::str = "asd";

Using this (the first case), you will still get an error if you use the non-default version of "asd", because the str constant is not defined for the general template.


>>Since i also got this error:

Yeah, I sort-of expected that. Maybe it can work with "nullptr", but Borland won't allow it, so you would need a pre-processor conditional.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>If I am just "using" it then does it mean, my function names are still in global namespace

Yes. The using statement simply makes it so that you don't have to qualify the namespace anymore when you _use_ things from that namespace. It doesn't mean that your code gets added to that namespace. Here's a quick example:

#include <iostream>

namespace foo {

  void print1() { 
    std::cout << "printing in foo!" << std::endl;
  };

};

namespace bar {
  
  using namespace foo;

  void print2() {
    std::cout << "printing from bar!" << std::endl;
  };

  void print3() {
    print1();     //call foo::print1() without needing foo::
  };
  
};

int main() {
  foo::print1();  //OK
  bar::print2();  //OK
  bar::print3();  //OK
  foo::print2();  //ERROR: print2 is not a member of namespace 'foo'
  print1();       //ERROR: print1 is not a member of the global scope.
  bar::print1();  //ERROR: print1 in not a member of namespace 'bar'
};

You get the idea, adding things to namespace 'bar' even though it uses namespace 'foo' will not add those things to the 'foo' namespace. And the logic goes the other direction too (e.g. "print1" from 'foo' does not get added to namespace 'bar'). So the using namespace statement is simply to shorten the syntax, but you can get into trouble, as so:

//.. as before

namespace bar {
  
  using namespace foo;

  void print1() {
    std::cout << "printing from bar!" << std::endl;
  };

  void print2() {
    print1();     //ERROR: print1() is ambiguous, do you mean bar::print1 or foo::print1.
  };
  
};

Sometimes, problems like that don't get …

mrnutty commented: I admire your ability to exhaust an answers! +13
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>I've heard that g++ emits more portable code but shouldn't they both be standard compliant?

Standard compliant? That's an ideal, not a reality. The only compiler that exists which is fully compliant to the C++98 standard is the Comeau compiler (and it took significant efforts to make it compliant, which was done just recently). Compilers are not, in general, compliant to the standard, strictly speaking. They all have their own "features". But yes, GCC tends to be, amongst the popular compilers, the most standard compliant one. At least, usually what the standard permits, GCC permits, with few exceptions, but GCC is also more permissive than the standard in some ways, most other compilers are too.

When it comes to programming with templates, that's where the differences between compilers tend to show up a lot more than in "normal" programming.

>>From what i've read in the '98 standard book this should be legal but feel free to prove me wrong.

You are right, it is legal, I mean the main part about using a char-pointer as template argument. Except that you made an error in your static constant definition, I'm guessing you meant to write:

template <const char* type> 
const char* asd<type>::str = "asd";

Now, lets take a look at those errors:

>>error: could not convert template argument ‘0’ to ‘const char*’

This is just a technicality, GCC doesn't seem to want to do integral to pointer casts in a template argument. GCC probably …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You cannot use an array that big. Your problem definition specified a limit of 1Mb, I guess it means you need to stick to that. You say that 6 digit numbers or less works fine in your range array. But more that 6 digit, i.e. 1 million, would cause the range array to be at least 8 Mb in size (each long long is at least 8 bytes), that is already way above your specified limit, and it also happens to be above your program's limit too, and that explains the error.

You need to find another strategy than holding all the values. For example, you could hold every 10 value and interpolate in-between them. It also depends on what function you have, you might be able to manipulate the math somehow to store only a subset of all the range and be able to efficient compute any other value from that subset.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Your problem is not related to the comp class or anything like that.

You have a memory corruption problem.

The problem is on the line 179 and 206:

for (int i=0; i < sizeof(rutor); i++){

The sizeof() operator returns the total size, in memory, of the variable or type that you give it, in this case "rutor". Because rutor is a static array of 8 Area objects, the value returned by sizeof(rutor) will by 8 * sizeof(Area) (8 times the size of an object of type Area). You are using the sizeof() operator as if it would return 8 in this case. In order to obtain the actual number of elements in a static array, you have to do:

for (int i=0; i < sizeof(rutor) / sizeof(Area); i++) {

The weird problems that you are getting is related to the fact that you write past the end of the array and overwrite other variables, causing weird stuff to happen. Replacing lines 179 and 206 with the above should solve your problems.

PS: Din engelska är inte dâligt als.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Yes, the std::sort function has a version that takes an extra parameter called "compare" which is used as a comparison function object (functor). The comparison function should be callable with two parameters of the type of the array that is being sorted and should return a bool value that should be true if the first parameter-value should be before the second one in the sorted list (i.e. the default is the less-than operator). So, you could define a functor for the comparison as follows:

struct compare_distances {
  double* dist_array;
  compare_distances(double* aDistArray) : dist_array(aDistArray) { };
  bool operator() (int i, int j) { 
    return (dist_array[i] < dist_array[j]);
  };
};

Then, you can use the std::sort function like so:

std::sort(idx,  //pointer to the first element of the array.
            idx + size, //pointer to the one-passed-last element of array.
            compare_distances(distance)); //comparison functor.
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You bubble sort method is missing one nested loop level.

The loop that you have will have the result of making the largest distance to end up at the end of the array (and thus the name "bubble" sort). But it _only_ takes the largest value to the end, all the other values are not sorted. You have to repeat the process as many times as there are values in the array. And each time you do the bubbling loop, you don't have to go all the way to the end, only as far as there are unsorted values left. So, you can do:

for ( j = size; j > 1; --j) {
    for ( i = 0; i < j-1; i++) {
      if (distance[idx[i]] > distance[idx[i + 1]]) {
        swp = idx[i];
        idx[i] = idx[i + 1];
        idx[i + 1] = swp;
      }
      //    cout << idx[i]<< endl;
    }
  }

This is why the bubble sort method has O(N^2) complexity, because it requires two nested loops proportional to N to do it.

If this is not an assignment problem, use the std::sort method instead.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The answers so far are very good and pretty complete, but I'd add a few things:

>>also can someone explain when i use unsigned variables??

Well, the only unsigned type you would really every use it unsigned int (or a similar type like uint64 and such). Unless you need an unsigned type of a specific number of bytes (e.g. for binary operations), then you typically only need the unsigned int type to describe some large size value (like an index or pointer). In that case, it is generally not even recommended to use "unsigned int", mostly by convention. The C++ standard defines a type called std::size_t which is preferred to describe array sizes or indices, which is the usual purpose of an "unsigned int".


>>Oh and when do we use constants? I mean I can just use a float or integer instead of const int or const float.. just don't change the value right?

"just don't change the value.." That's pretty weak. The same thinking would lead to declaring "hey guys, let's just not commit crimes, ok?" and then say that you don't need cops anymore. The compiler is the police service in the source code. Marking a variable as const makes sure that any intentional or non-intentional changes to the value will be caught by the compiler. It helps catch a classic typo like if(PI = my_angle) . This is often the main reason for using const, minimize the chance for erroneous code …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The stringstream class is your best friend for this purpose.

Use the getline() function to obtain the string for the entire line, then pass that string to a stringstream object and then extract the tokens from the stringstream.

For dealing with multiple and variable-number of arguments, you can do what WaltP suggested, you take each token one at a time and figure out what tokens you should see next, and so on.

I could also recommend that you make a queue of strings in which to align all the tokens that you read from the input. Then, your command-handlers can simply inspect the next tokens on the queue and read off as many as they need or recognize (as options).

Other libraries that can help you is the Boost.Tokenizer, Boost.Regex (or new standard Regex library), and Boost.Spirit/Phoenix (brace yourself!).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Now size of final will be: 4032. as Final will have common A through B and C. Here is the break down of the memory allocation:
4000 for int array.
4 for int c in C + 4 byte padding.
4 for int b in B + 4 byte padding.
16 byte for vtable pointer.

Just a correction on the breakdown of memory allocation. None of the classes have virtual functions, so they will not have vtable pointers. Here is the correct breakdown (in order):
4000 bytes for int array in A.
8 bytes for the pointer to the virtual base-class (A) object of B.
4 bytes + 4 bytes padding for the int b in B.
8 bytes for the pointer to the virtual base-class (A) object of C.
4 bytes + 4 bytes padding for the int c in C.
___
4032 bytes in total.

In order to implement virtual inheritance, all the classes that are virtually derived from a base-class will need a pointer to the "this" pointer of the virtual base-class because it could move with respect to the derived class's "this" pointer depending on the overall inheritance hierarchy.

I also recommend Marshall Cline's explanations of it. Here

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>May I ask, if you can help me with a conceptual example?

Ok, lets assume that you are building a numerical integrator for some dynamic system (an example I know very well). A classic (non-inverted) control flow for this problem would be to do this:
1) Setup the dynamic system and numerical integrator.
2) Set the initial state-vector.
3) Run the integrations:
3a) Perform one time-step of integration.
3b) Record the resulting state-vector after one step.
3c) Repeat until the end.
4) Record the end result of the integration.

The above is the normal control-flow, but this does not lend itself easily to the MVC pattern.

In MVC, the controller is used to setup the dynamic system and the integration parameters (time-step, tolerance, etc.). The model actually performs the numerical integration. The view is used to show the results, either as a graph or table, or file output, whatever.

You can see from the normal control flow that it requires the View to be in control of the integration (do one step, and record, and repeat). However, if you give a Visitor to the numerical integrator, you can invert that control flow to put the Model in control of the integration. So, you can define a visitor as so:

class IntegrationVisitor {
  public:
    virtual bool keepGoing() = 0;
    virtual void initialize(double aInitTime, const std::vector<double>& aInitState) = 0;
    virtual void recordState(double aTime, const std::vector<double>& aState) = 0;
    virtual void …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>> Now I need to register callback function so that when Model is done it will update view using that callback.

You have stumbled upon the reason why I don't like MVC very much. The "idea" of MVC is that the Model should be only a slave to the other components (I say "idea" because it's an old theoretical idea from a time where GUI was more theoretical than practical). Generally, people realize this by having the View run in a loop, always querying the state of the Model and updating anything that changes (or updating everything). Similarly, the Controller runs in a loop catching events of user input. While the Model just sits there, being a slave to the other two. For the Controller, it is totally appropriate. But for the View, it is just stupid and wasteful. So, yeah, you need callbacks initiated by the Model in order signify that some things have changed and need to be updated in the View. But how?

The idea of MVC is to separate the three things, but to what level? Conceptually or computationally. If you just want to conceptually separate the View from the Model, then you need to create an abstraction that wraps the notifications that the View wishes to respond to. Personally, I like to use the Visitor Pattern for this (and it is pretty much the only place I use it), in a manner that implements Inversion of Control. This way, on an abstract level, …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Or Qt,
Or SDL.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

P has a function setupBuffer() and is called by the constructor. I want the child class to overide it such that when the parent calls setupBuffer() it calls the child's version. Should either be virtual?

No. You cannot achieve this, whether your function is virtual or not. You cannot safely call a virtual function from a parent-class constructor and expect it to call the function from the child-class. The virtual dispatch mechanism is not put in place until the object is fully constructed. You can call other non-virtual functions without fear, you can even call virtual functions, but it won't be the child-class version of the function that will be called, it will be the parent-class version, if it exists.

Anyways, just don't do that, find another way.

Another situation is when I want the child class always to be called even if casted as the parent.

By "casted" if you mean that you cast a reference or pointer to a child-class object into a reference or pointer to a parent-class object, then, yes, that is exactly what virtual functions are for, and this "substitutability" of a child-class pointer (or reference) where a parent-class pointer (or reference) is needed is called "polymorphism".

In what cases would doing:

void c::func()
{
p::func();
}
not work, or will it always work regardless of virtual being tagged to function?

This will always work, regardless of the "tags" on the functions. The difference is not within the …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I'm no expert on audio/video streaming. On most of my projects, either other people dealt with that, or we had an off-the-shelf solution requiring no additional low-level implementation.

In any case, contact the hardware's manufacturer and ask them about the methods suggested / provided for outputting audio/video stream. As for libraries that are typically used for that, I don't really know, the only libraries I know (besides manufacturer-provided libraries) are gstreamer and opencv (an ex-colleague of mine got one stereo-camera system, three free cameras and a pivoting laser range finder all working with OpenCV, and it took him a few weeks to get it all up and running, so it seems pretty easy to do).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>Union with a name seems a lot like a structure or a class,

That's because a union is a heck of lot like a struct or class except that all members share the same address in memory and the union is as large as the largest (aligned) data member it contains. Other than that, unions are similar to structs and classes in many ways, they can even be templated, have member functions, etc. But they have several restrictions, like they cannot have virtual members, cannot contain non-POD data members, cannot be part of an inheritance scheme, etc. According to the standard (C++98), unions are considered to be a kind of "class". And the new standard will even expand the capabilities of a union-types.

>>but a union without a name seems pointless to me.

It is certainly not pointless. Say you want a class that has some data members to occupy the same memory and others to have separate places in memory, then you can use a nameless union for that.

>>So whats the point of it?

The point is to simplify the syntax such that you don't have to name the union data member each time you want to address it.

>>The first example just looks like a declaration of data type inside a declaration of another data type

That's exactly what it is.

>>and that supposed to be impossible,

Who told you that? Declaring a type within a type is …

sergent commented: that explains a lot! Thanks! +5
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Then you need to use an interrupt based on the real-time clock alarms. This is the only method to precisely wake-up a thread based on hard real-time constraints. I don't know much about windows CE so I can't really help you with the details, you need to browse msdn reference pages for instruction of setting up the RTC timer and handling the interrupt.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Well, the new standard came out yesterday. It's not even published yet. Don't expect C++0x / C++11 books just yet. And be even more patient for compliant compilers.

Right now, the best resources for C++11 are:

The C++0x wikipedia page.

Bjarne Stroustrup's C++0x FAQ page.

The last published draft of the standard. n3242. Which is pretty much the same as the FDIS that was just approved.

And some tutorials that exist out there, including mine.

Ancient Dragon commented: good stuff to know :) +17
jonsca commented: Agreed, and nice tutorial +14
Chilton commented: Thanks a lot for the help. +3
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You can use the Boost.Date-Time library and the Boost.Thread library, they offer timing functions with, in theory, a precision up to nano-seconds and similarly for the thread sleeping functions. Of course, when your system cannot support nanosecond timing then it will be rounded to the smallest possible precision your computer supports (usually some fraction of a micro-second, most recent computers support at least micro-second precision, unless it is really old).

In general, you can't really depend on the thread system to be precise even if your clock is precise enough. The problem is that putting threads to sleep, scheduling them, waking them up and such, are all things that the OS can't guarantee to do with precise timing. But, for fractions of milliseconds, it's not so bad. To get really precise timing on thread executions, you need a Real-Time Operating System (RTOS), which means that it can implement what is called "hard real-time" where you can specify very precise interrupt intervals to restart a thread (it uses low-level interrupts that can provide real guarantees for precise timing, close to the clock-freq. of your processor).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Instead of bothering yourself with doing copies of backup files with the tilde mark. I would suggest you just use a subversion control system. I recommend Git. At any time, you can retrieve the entire history of the modifications to any of your source files ("diff" style). That's very easy to use, and git is not centralized, so it does not require a server running it or anything, that's what I do for all my work files, including files that aren't source files, I can keep a triple backup of all my files (and their entire modification history), on three separate hard-drives.

As for build system, I recommend cmake, it is much nicer than those all-too-limited makefiles.

To solve your problem with the makefile, I can't really help you. You should probably not implement this mechanism in a makefile, use a shell script instead, which you can call from your makefile "backup" target.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>#2

You cannot use the == operator for comparing C-strings (arrays of chars), this will only compare the pointer values. To compare the actual C-strings, you need to use the strcmp function.

For the rest, I don't understand the questions or what you want.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Just make the handler for the click button event in the Interface class, and then call a function of the DAQCycle class, and pass it the "this" pointer of the Interface object.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

This:

l.pHead=p.pNext;
p.pNext=NULL;
Thus, l.pHead=NULL;

is wrong. You are thinking about the = operator as if it was like in mathematics. When you write "a = b" in C++ (and in almost any programming language), it means that you copy the value of b and assign it to a. After the expression has executed, there is no relationship between a and b. Changing b's value will not change a's value. It is not like a mathematical equality relation where you state "a" is equal to "b" forever and always. It's a different logic in programming, it's just execution of one line after the other.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>I was actually referring to the tendency of some compilers to delay allocation of a variable until it's absolutely needed rather than doing it when the declaration is made.

That sounds very peculiar. Do you have any reference describing this? It would seem to me like a violation of the "as if" rule for allowed optimization (I thought the only allowed exception to the rule was elision of temporaries). I would be very interested in learning what that's about.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>Or am I mis-interpreting something?

No, your logic is good, it is just that you seem to be tying the concept of "polymorphism" to a mechanism for run-time flexibility. Of course, my dynamic example was very trivial and didn't show the run-time flexibility that dynamic polymorphism gives you. Of course, the compiler optimization turns my dynamic polymorphism example into static polymorphism, but I was making a point about polymorphism implemented dynamically (virtual functions) or statically (templates) and how they both achieve polymorphism. But like you pointed out, they are different, of course, they are not equivalent but they are both forms of polymorphism. As you know, polymorphism is a means to achieve flexibility in a software by being able to substitute anything that implements a given abstraction (a base-class or a template-argument's concept) into an algorithm or method. The difference between static and dynamic polymorphism is that the static version only provides that flexibility (or substitutability) at compile-time, while the dynamic version allows you to get run-time flexibility. That's the difference, and that is what should be the motivation for using dynamic polymorphism instead of static. If you need run-time flexibility then use dynamic polymorphism, if not then use static polymorphism, because you shouldn't pay the price for run-time flexibility if you don't need it (the "price" of run-time flexibility is the slight virtual-dispatch overhead, but mainly the lack of opportunity of performance optimizations by the compiler such as inlining and elision of temporaries). In the tradition of C++, …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>time to write a function filled with string comparisons to each function I write...

There is certainly a better solution than doing this. What are you trying to achieve?

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

This is a question that comes up from time to time on forums on C++. And, I'm convinced now that there is no way to do this. I hope I'm wrong, but I think there is little chance.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Read this.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>Could a resizing of the std::vector cause the whole AudioBuffer object to be relocated?

No. Absolutely not. You can eliminate that possibility, and look for another cause. Post more code on the context of the problem, and we might help.

>>If you have any good resource on program design that show / recommend using references over pointers, I'd be very intrested to hear where I can get it!

Well you can look at this FAQ. But, other than that, I don't know.

I've actually been preparing a tutorial on a subject very closely related to this ("avoiding memory problems by design"), as a consequence of doing a code-review on a library with many such problems. Hopefully it will be able to complete it, and post it on this forum, sometime soon.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Tell your prof to move into the 21st century, because C++ has. Learning pre-standard C++ is a waste of time.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

This is a really weird error, and I'm sure there is something you are not telling us. My guess would be that the audioBuffer gets relocated.

The fact that you reallocate or change the std::vector member (I assume is held by value in audioBuffer, as it should) should not cause your pointer to it to be wrong. That's simply impossible in C++. The only way that is possible is if the audioBuffer object gets relocated, which would relocate the std::vector member along with it.

You will need to post more details about the implementation of ResourceHolder and AudioBuffer, because the error cannot be diagnosed from this simple description. One thing for sure, it is not a problem about the std::vector object somehow relocating itself, objects cannot do that in C++, because of value-semantics, objects are only relocated (moved or copied) when their owner (parent object) gets moved.

Generally, it is bad practice to "export" a pointer to a data member from an object. That's dangerous code because you can never be sure that the data member still exist or is still at the same place in memory. Find an alternative. Also, rely on you compiler to optimize things, for example, there is no advantage to do this:

AudioBuffer* audioBuffer   = resourceHolder->getAudioBufferPointer();
std::vector<float>* vector = audioBuffer->getVectorPointer();

// blah blah, read the vector
x = vector->at(0);
// use the vector again and again.

Compared to doing this:

// blah blah, read the vector
x = resourceHolder.getAudioBufferPointer().getVectorPointer().at(0);
// …
harryhaaren commented: Good advice, clearly worded +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I think that your compiler is a piece of sh**. Typically I don't recommend people use a Microsoft compiler that is older than 2008, because they are notoriously buggy, but 2008 and newer are fine.

The first error you report about the redeclaration of count is due to the fact that your compiler does not respect the standard scoping rules. In other words, the compiler is broken and non-standard.

The second batch of warnings are due to a bad implementation of the C++ standard libraries.

So, the compiler that you are using is the problem and is causing those warnings, not the code. The 1998 microsoft compiler basically pre-dates the first C++ standard (from 1998), so it is not very surprising. Get a more up-to-date compiler, either a newer version of Visual Studio (or Express edition (free)) or another IDE like CodeBlocks (with MinGW GCC compiler).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Your if statement about the allocation cannot be written that way. You have to write:

if (names == 0 || price == 0)

The way you had it with the comma is not correct. The compiler will accept the syntax but it is not correct.

The warning comes from the fact that you don't always match your new statements with a delete statement. But you do. I think your compiler is stupid (and old, 98). It is probably because of the (nothrow) new operator which is kinda weird, it is usually preferable to use the normal one, or none at all. In C++, for this kind of thing, it is much preferred to use a std::vector to store dynamic arrays, in part because it is more safe in the face of exceptions (which is the reason for the warning).

You also have an error in your code. If you fail to allocate the memory for the arrays, you only output a error message, but you do not terminate the program, meaning that there is a chance that the arrays are traversed (to print the bill) which would cause a run-time error.

The last problem, not an error but bad practice, is your obsession with declaring all the variables at the top of the program (or scope). It's generally good practice to declare variables at the place where they are first used, because it minimizes the chance of using them uninitialized and it makes the …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Well, pretty much everywhere in the code, you use a single < where you need two (outputting with streams). That will fix your problem. And you also need to #include <cstring> to get the strlen function.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Why does the database function needs to be passed anything? From the looks of the function, all it does it use the "f" variable as a local variable, and it doesn't use its passed-value for anything. Just make it a local variable and make the database function a function without parameters.

The error is pretty obviously because "f" was never declared in the menu() function, just like the compiler says. You could declare a variable "f" in menu() and pass it to database(), but I see no point in that, because database() doesn't use that value.

Finally, if you want to practice your C++ programming, maybe you should try not to use C functions (like fopen, printf, etc.).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>> I have not given a size to the vector.Could it be because of that?

Well, if your vectors are empty, how could you expect to be able to access elements of them? I think people reading your example assumed it was not real code, just an example of the syntax that was erroneous.

Is your error occurring when you run the program or when you compile it?

You have to populate a vector with elements before you can access any. That's pretty obvious.