0

I've set up two classes, Dog and AnotherDog. Dog is not meant to be a base class for AnotherDog.

In AnotherDog, I have a Dog object. Within that Dog object is a member array. When an AnotherDog object call its Dog member, then has the member loop thru its member array, I get the wrong results.

#include <iostream>

class Dog
{
private:
    int m_NumberOfBarks;
    int m_Decibels[];
public:
    Dog();
    ~Dog();

    void setBarkDecibels(int decibel1, int decibel2);
    void loopDecibels();
};

Dog::Dog() : m_NumberOfBarks(2){}
Dog::~Dog(){}

void Dog::setBarkDecibels(int decibel1, int decibel2){
    m_Decibels[0]=  decibel1;
    m_Decibels[1]=  decibel2;
}

void Dog::loopDecibels(){
    for(int i=0; i<m_NumberOfBarks; ++i){
        std::cout << i << ' ' << m_Decibels[i] << std::endl;
    }
}


class AnotherDog
{
private:
    Dog m_Dog;
public:
    AnotherDog();
    ~AnotherDog();

    Dog getDog();
};

AnotherDog::AnotherDog(){
    m_Dog.setBarkDecibels(10, 100);
}
AnotherDog::~AnotherDog(){}

Dog AnotherDog::getDog(){
    return m_Dog;
}


int main(){
    AnotherDog goodDog;
    goodDog.getDog().loopDecibels();
    return 0;
}

I want void Dog::loopDecibels() to print 10 and 100, along with the index.

Instead I get this:

0 0
1 4196480

What am I doing wrong?

How do I achieve the result I want?

Username
  • 3,463
  • 11
  • 68
  • 111
  • 4
    `int m_Decibels[];` is not valid. You need to specify a size for the array (or better yet, use a `std::vector`). – crashmstr Feb 25 '16 at 17:08
  • use std::vector instead in int[] – pm100 Feb 25 '16 at 17:12
  • @crashmstr, it is somewhat valid. There is an old arcane rule allowing to have your last member of the struct defined in this manner - and than it can be used as a pointer to memory beyond the struct - and some compilers still allow it. – SergeyA Feb 25 '16 at 17:13
  • Unrelated: Why not have 1 dog class, create 2 different dogs, and either give dogs a method to interact with each other or have the object that owns both dogs somehow negotiate interactions between them? – RyanP Feb 25 '16 at 17:14
  • @SergeyA This? http://stackoverflow.com/questions/16553542/c-struct-hack-at-work – PaulMcKenzie Feb 25 '16 at 17:24
  • @PaulMcKenzie, yeah. – SergeyA Feb 25 '16 at 17:27

1 Answers1

4

Your program exhibits undefined behaviour.

 int m_Decibels[];

Declares a pointer to int, and does not allocate any memory for the pointer to point to. Pointer remains uninitialized in the class constructor (since you do not initialize it). When later you do

m_Decibels[0]=  decibel1;
m_Decibels[1]=  decibel2;

You are dereferencing this pointer, which is a no-no. To fix this, you can use a fixed-size array:

int m_Decibels[2];

The other side of the coin is that you are returning an instance of Dog from your getDog by value. When you are setting your decibels on this particular instance, it has no effect on the original dog member of the class. To fix this, you might want to return your object by a reference, like this:

   Dog& getDog(); // and corresponding change in the definition
SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • I've added a size to the array as @crashmstr recommended. Can you tell me what you mean by "When you are setting your decibels on this particular instance, it has no effect on the original dog member of the class"? Are you talking about `m_dog`? – Username Feb 25 '16 at 17:32
  • 1
    @Username, when you return your `dog` by value, you are returning a copy. Modifications to the copy do not affect original. – SergeyA Feb 25 '16 at 17:38
  • Then I should return by address if I want to modify 'm_dog' when called by 'getDog()'? 'return &m_dog'? – Username Feb 25 '16 at 17:44
  • 1
    @Username, better return by reference. Makes it much clearer. – SergeyA Feb 25 '16 at 17:46
  • Ok, if you add that to your answer, with the suggestion to assign a size to the array, I can mark your answer the correct one. – Username Feb 25 '16 at 17:49