Grr. "Cannot declare variable 'lightOutlet' to be of abstract type '...'

I'm getting the error "Cannot declare variable 'lightOutlet' to be of abstract type 'basicTimerOutletObject'. I'm not sure why the compiler is still thinking that basicTimerOutletObject is an abstract type; as far as I can tell I've defined all the functions which need to be defined in it. I'm using the Eclipse IDE with the Arduino plugin.

The main program file is controller_alpha_04.cpp.

/******************************************
 * controller_alpha_04.cpp
 
#include "controller_alpha_04.h"

#include "OutletObjects.h"
#include "Wire.h"
#include "RTClib.h"
#include "basicTimeFunctionsLib.h"
#include "sensorGrabber.h"



#define LIGHT_PIN 7;
#define PUMP_PIN 8;

RTC_DS1307 RTC;

byte lightPin = LIGHT_PIN;
byte pumpPin = PUMP_PIN;

combinedDataObject combinedData;
sensorGrabber sensorPoller(&combinedData, &RTC);
timeObject _testtimeOn(9,50,0);
timeObject _testtimeOff(10,0,0);
timeObject _testduration(0,0,30);

basicTimerOutletObject lightOutlet;//(lightPin, &combinedData, _testtimeOn, _testtimeOff);  <-- Compiler flags error here.

void setup()
{
	Serial.begin(57600);
	Wire.begin();
	RTC.begin();
	lightOutlet.begin(lightPin, &combinedData);
	lightOutlet.set(_testtimeOn, _testtimeOff);
}

void loop()
{

}

Here's the header file that deals with that object:

/*
 * OutletObjects.h
 *
 *  Created on: Apr 12, 2012
 *      Author: Sev
 */

#ifndef OUTLETOBJECTS_H_
#define OUTLETOBJECTS_H_

#include "Arduino.h"
#include "sensorGrabber.h"
#include "timerClasses.h"


class outletObjectInterface
{
public:
	virtual void begin() = 0;		// Must be passed the address of the pin it should control in setup.
	virtual void evaluate() = 0;						// Call to make the outlet evaluate its logic.
	virtual void set()= 0;
	virtual void print() = 0;		// Call to print settings and status to Serial.  Prints on a single line, does not <cr>.
	void setManualOverride(boolean _state);				// Call to manually turn the outlet on or off and prevent evaluation of outlet logic
	void freeManualOverride(void);						// Call to free the manual override and allow the outlet to return to normal function
	boolean isInitialized(void) ;
	boolean isSet(void) ;
	boolean isReady(void) ;
	boolean getOutletPinState(void);
protected:

	boolean outletOverrideState;
	boolean overrideOn; // True if manual override is on
	boolean outletPinState;
	byte outletPin;
	boolean outletInitialized; // Has the object been initialized?  Should be set false by constructor
	boolean outletSet; // Has the object been set properly?  Should be set false by constructor.
};

class basicTimerOutletObject : public outletObjectInterface
{
public:
	void begin(byte _pin, combinedDataObject * _data);
	void evaluate(void);
	void set(timeObject _on, timeObject _off);
	void print(void);

	basicTimerOutletObject(void);
	basicTimerOutletObject(byte _pin, combinedDataObject * _data, timeObject _timeOn, timeObject _timeOff);

protected:
	basicTimerObject timer;
	combinedDataObject * data;

};


class basicThermostatOutletObject : public outletObjectInterface  // need to add a hysteresis timer.
{
public:
	void begin(byte _pin, combinedDataObject * _data);
	void evaluate(void);
	void set(temperatureObject _target, boolean _invert);
	void print(void);

	basicThermostatOutletObject(void);
	basicThermostatOutletObject(byte _pin, combinedDataObject * _data, temperatureObject _setPoint, boolean _invert);

protected:
	temperatureObject setPoint;
	combinedDataObject * data;

	int setTemp; // Raw temperature that the thermostat is set to trigger at
	boolean invertOperation; // set true if you want the thermostat to kick in if the temperature is above the setpoint, as with an AC.
};

class timerTimerOutletObject : public outletObjectInterface
{
public:
	virtual void begin(byte _pin, combinedDataObject * _data);
	virtual void set(timeObject _on, timeObject _duration);
	virtual void evaluate(void);
	virtual void print(void);

	timerTimerOutletObject(void);
	timerTimerOutletObject(byte _pin, combinedDataObject * _data, timeObject _timeOn, timeObject _duration);
protected:
	basicTimerObject timer;
	combinedDataObject * data;
};


#endif /* OUTLETOBJECTS_H_ */

And here's the cpp file for the above header file:

/*
 * OutletObjects.cpp
 *
 *  Created on: Apr 12, 2012
 *      Author: Sev
 */

#include "OutletObjects.h"



void outletObjectInterface::setManualOverride(boolean _state)
{
	overrideOn = true;
	outletOverrideState = _state;
	outletPinState = outletOverrideState;

	evaluate();
}

void outletObjectInterface::freeManualOverride(void)
{
	overrideOn = false;
	evaluate();
}

boolean outletObjectInterface::isInitialized(void)
{
	return outletInitialized;
}

boolean outletObjectInterface::isSet(void)
{
	return outletSet;
}

boolean outletObjectInterface::isReady(void)
{
	return ( outletInitialized && outletSet);
}

boolean outletObjectInterface::getOutletPinState(void)
{
	return outletPinState;
}

void basicTimerOutletObject::begin(byte _pin, combinedDataObject * _data)
{
	outletPin = _pin;
	data = _data;				// data is a pointer to the main combinedDataObject for the program.
	outletInitialized = true;
	timer.setDataSource(data);
}


void basicTimerOutletObject::set(timeObject _on, timeObject _off)
{
	timer.setTimers(_on, _off);
	outletSet = true;
}

void basicTimerOutletObject::evaluate(void)
{
	timer.tick();
	if(overrideOn == true)
	{
		outletPinState = outletOverrideState;
		digitalWrite(outletPin, outletPinState);
		return;
	}
	outletPinState = timer.getState();
	digitalWrite(outletPin, outletPinState);
}

void basicTimerOutletObject::print(void)
{
	if (isReady() == false) { Serial.print("NOT READY"); return;}
	timeObject on = timer.getTimeOn();
	timeObject off = timer.getTimeOff();
	timeObject _now = timer.getcurrenttime();
	Serial.print("Time On: ");
	on.printTime();
	Serial.print("  Time Off: ");
	off.printTime();
	Serial.print("  Time Now: ");
	_now.printTime();
	Serial.print("  Outlet is");
	if(getOutletPinState() == true) Serial.print("ON");
	if(getOutletPinState() == false) Serial.print("OFF");
	if(overrideOn == true) Serial.print("  MANUAL OVERRIDE ON");
}


basicTimerOutletObject::basicTimerOutletObject(void)
{
	outletInitialized = false;
	outletSet = false;
}

basicTimerOutletObject::basicTimerOutletObject(byte _pin, combinedDataObject * _data, timeObject _timeOn, timeObject _timeOff)
{
	outletInitialized = true;
	outletSet = true;
	timer.setTimers(_timeOn, _timeOff);
	data = _data;
	outletPin = _pin;
	timer.setDataSource(data);
}

void basicThermostatOutletObject::begin(byte _pin, combinedDataObject* _data)
{
	outletPin = _pin;
	data = _data;
	outletInitialized = true;
}

void basicThermostatOutletObject::set(temperatureObject _target, boolean _invert)
{
	setPoint = _target;
	invertOperation = _invert;
	outletSet = true;
}

void basicThermostatOutletObject::evaluate(void)
{
	if(isReady() == false) { Serial.println("ERROR, NOT READY"); return;}
	if(overrideOn == true) { outletPinState = outletOverrideState; digitalWrite(outletPin, outletPinState); return;}
	if(invertOperation == false)
	{
		if(data->getTempRaw() < setPoint.getTempRaw()) outletPinState = true;	// Some basic hysteresis; this if statement could be accomplished without with "outletPinState = (data->getTempRaw() < setTemp.getTempRaw())
		if(data->getTempRaw() > setPoint.getTempRaw()) outletPinState = false;
	}
	else
	{
		if(data->getTempRaw() < setPoint.getTempRaw()) outletPinState = false;
		if(data->getTempRaw() > setPoint.getTempRaw()) outletPinState = true;
	}

	digitalWrite(outletPin, outletPinState);
}

basicThermostatOutletObject::basicThermostatOutletObject(void)
{
	outletInitialized = false;
	outletSet = false;
}

basicThermostatOutletObject::basicThermostatOutletObject(byte _pin, combinedDataObject * _data, temperatureObject _setPoint, boolean _invert)
{
	outletInitialized = true;
	outletSet = true;
	outletSet = true;
	setPoint = _setPoint;
	invertOperation = _invert;
	outletPin = _pin;
	data = _data;
}


void basicThermostatOutletObject::print(void)
{
	if (isReady() == false) { Serial.print("NOT READY"); return;}
	Serial.print("Therm Setpoint:");
	Serial.print(setPoint.getTempF(), 2);
	Serial.print("*F  Invert:");
	if(invertOperation == true) Serial.print("On");
	if(invertOperation == false) Serial.print("Off");
	Serial.print("   Current Temp:");
	Serial.print(data->getTempF(), 2);
	Serial.print("*F   Outlet is ");
	if(getOutletPinState() == true) Serial.print("ON");
	if(getOutletPinState() == false) Serial.print("OFF");
	if(overrideOn == true) Serial.print("  MANUAL OVERRIDE ON");
}

(removed timerTimer object stuff to save space)

Because this...

class outletObjectInterface
{
public:
virtual void begin() = 0; // Must be passed the address of the pin it should control in setup.

...and this...

class basicTimerOutletObject : public outletObjectInterface
{
public:
void begin(byte _pin, combinedDataObject * _data);

...are different methods. You failed to override the abstract begin in outletObjectInterface but instead overloaded the method name begin.

Thanks! How would I override the method instead of overloading it? Sorry, this is my first venture into any 'real' kind of OO program that actually uses inheritance.

I believe the problem can be resolved by you answering the question, "Why is begin virtual?"

begin() is virtual because it must be redefined in later classes; what the object does with data passed to it there may differ in later implementations. I thought that by creating a pure virtual function in the base class (and not defining it there) would cause the begin() function to be overridden by the begin() function declared in classes derived from it. I may be completely off base, but this was my understanding of what a pure virtual function did.

begin() is virtual because it must be redefined in later classes

You assume "virtual" and "redefine" are intertwined.

Try removing begin from outletObjectInterface and making begin a static method in the other classes (remove virtual). Does the code compile? Does it do what you expect?

Hrm. Actually, that should work for the begin() and set() functions. However, evaluate() and print() have to be part of the base interface (along with setManualOverride(), freeManualOverride, and the other functions there, but their implementation won't change) since I eventually want to create objects derived from this class dynamically and be able to iterate through them with a pointer.