Site Sponsors:
GNU C++: Ineritance & Default Parameter Confusion 
For those who like to use C++, the sole justification for many is the ability to implement a common signature over several related implementations.

Commonly known as "inheritance," when we need to use a parent's function / signature, yet provide a unique child-implementation of our own, we call it "polymorphism."

C++ Slicing


When it comes to using default parameters, we should note that those actually applied to our call will depend upon the receiving type.

No matter if we are using a vtable or no (*), this ability to "chop off" children definitions in C++ is a remnant of something called "Slicing."

By way of example, given the following base class & factory enumeration:
namespace BlogNouns {

enum Types {
typeThing, typePlace, typePerson
};

class Thing {
public:
virtual void speak(const char *psz = "Ima Thing") {
printf("Thing: %s\n", psz);
}

static Thing& Create(Types which);
};
}
, upon creating a few children we shall also provide a different default "speak" parameter:
    class Place : public Thing {
public:
virtual void speak(const char *psz = "Ima Place") {
printf("Place: %s\n", psz);
}

};

class Person : public Place {
public:
virtual void speak(const char *psz = "Ima Person") {
printf("Person: %s\n", psz);
}

Having set the stage for the first demonstration, supporting the aspersion =) we'll see:
using namespace BlogNouns;


int main(int argc, char** argv) {
puts("MyNouns");
Thing& noun = Thing::Create(Types::typePerson);
noun.speak();
delete &noun;

noun = Thing::Create(Types::typePlace);
noun.speak();
delete &noun;

noun = Thing::Create(Types::typeThing);
noun.speak();
delete &noun;

return 0;
}

-will use the default receiving-type ("Thing") parameter:

MyNouns
Person: Ima Thing
Place: Ima Thing
Thing: Ima Thing

Conversely however, whenever we change the receiving type to match the type actually created, we see that we will - instead - use that associated receiving-type's default parameter:

int main(int argc, char** argv) {

puts("BlogNouns");
Person& person = (Person&)Thing::Create(Types::typePerson);
person.speak();
delete &person;

Place& place = (Place&)Thing::Create(Types::typePlace);
place.speak();
delete &place;

Thing& thing = Thing::Create(Types::typeThing);
thing.speak();
delete &thing;

return 0;
}

BlogNouns
Person: Ima Person
Place: Ima Place
Thing: Ima Thing
Finally, note that I'm-a using:
c++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.



Sharing is caring,


-Rn

(*) Here is the "sliced proof" that virtual table (vtable) definitions do not matter:

With VTABLES:


/* Virtual - Replacing parental definitions.
*/

#include <iostream>

using namespace std;

namespace BlogNouns {

enum Types {
typeThing, typePlace, typePerson
};

// Simplified

class Thing {
public:
virtual void speak(const char *psz = "Ima Thing") {
printf("Thing: %s\n", psz);
}

static Thing& Create(Types which);
};

class Place : public Thing {
public:
virtual void speak(const char *psz = "Ima Place") {
printf("Place: %s\n", psz);
}

};

class Person : public Place {
public:
virtual void speak(const char *psz = "Ima Person") {
printf("Person: %s\n", psz);
}

};

Thing& Thing::Create(Types which) {
switch (which) {
case typeThing:
return *(new Thing);
case typePerson:
return *(new Person);
case typePlace:
return *(new Place);
}
}

}

using namespace BlogNouns;


int main(int argc, char** argv) {

{
puts("MyNouns");
Thing& noun = Thing::Create(Types::typePerson);
noun.speak();
delete &noun;

noun = Thing::Create(Types::typePlace);
noun.speak();
delete &noun;

noun = Thing::Create(Types::typeThing);
noun.speak();
delete &noun;
}
puts("BlogNouns");
Person& person = (Person&)Thing::Create(Types::typePerson);
person.speak();
delete &person;

Place& place = (Place&)Thing::Create(Types::typePlace);
place.speak();
delete &place;

Thing& thing = Thing::Create(Types::typeThing);
thing.speak();
delete &thing;

return 0;
}


Output:

MyNouns
Person: Ima Thing
Place: Ima Thing
Thing: Ima Thing
BlogNouns
Person: Ima Person
Place: Ima Place
Thing: Ima Thing


Without:


/* No Virtuals - Simply Overriding parental definitions.
*/
#include <iostream>

using namespace std;

namespace BlogNouns {

enum Types {
typeThing, typePlace, typePerson
};

// Simplified

class Thing {
public:
void speak(const char *psz = "Ima Thing") {
printf("Thing: %s\n", psz);
}

static Thing& Create(Types which);
};

class Place : public Thing {
public:
void speak(const char *psz = "Ima Place") {
printf("Place: %s\n", psz);
}

};

class Person : public Place {
public:
void speak(const char *psz = "Ima Person") {
printf("Person: %s\n", psz);
}

};

Thing& Thing::Create(Types which) {
switch (which) {
case typeThing:
return *(new Thing);
case typePerson:
return *(new Person);
case typePlace:
return *(new Place);
}
}

}

using namespace BlogNouns;


int main(int argc, char** argv) {

{
puts("MyNouns");
Thing& noun = Thing::Create(Types::typePerson);
noun.speak();
delete &noun;

noun = Thing::Create(Types::typePlace);
noun.speak();
delete &noun;

noun = Thing::Create(Types::typeThing);
noun.speak();
delete &noun;
}
puts("BlogNouns");
Person& person = (Person&)Thing::Create(Types::typePerson);
person.speak();
delete &person;

Place& place = (Place&)Thing::Create(Types::typePlace);
place.speak();
delete &place;

Thing& thing = Thing::Create(Types::typeThing);
thing.speak();
delete &thing;

return 0;
}


Output:

Thing: Ima Thing
Thing: Ima Thing
Thing: Ima Thing
BlogNouns
Person: Ima Person
Place: Ima Place
Thing: Ima Thing

[ add comment ] ( 207 views )   |  permalink
zPython Clock, Revisited 
Here is an upgrade for zClock:



from tkinter import *
import time

zProgram = Tk()
zProgram.title("zPython Clock - Soft9000.com")
zClock = Label(zProgram,
font=('ariel', 72, 'bold'),
bg='gold',
fg='white')

zDay = Label(zProgram,
font=('ariel', 36, 'bold'),
bg='gold',
fg='green')

zDate = Label(zProgram,
font=('ariel', 36, 'bold'),
bg='gold',
fg='blue')

zClock.pack(fill=BOTH, expand=1)
zDay.pack(side='left', fill=X, expand=1)
zDate.pack(side='right', fill=X, expand=1)


def zTimer():
zClock.config(text=time.strftime('%H:%M:%S'))
zDay.config(text=time.strftime('%a'))
zDate.config(text=time.strftime('%m/%d/%y'))
zClock.after(500, zTimer)


zTimer()
zProgram.mainloop()


Here is zVideo :-)


[ add comment ] ( 201 views )   |  permalink  |  related link
zClock: Python3 Clock in 11 Statements 
When the atomic clock went on the fritz lately (probably was the first popular commercial version ever available!) I went lookin'.

Finding a few for under $20, it occurred to me that - attached as we are to the DST-capable world-time-zone, that I could easily slap one together in Python.



Looking for a way to keep braggin' over how easy it is to get things done using Python 3, I decided to see just how few lines I could use to encode the idea.

Here is what I came up with:

from tkinter import *
import time


zProgram = Tk()
zProgram.title("zClock: Python3 Clock in 11 Statements")
zClock = Label(zProgram,
font=('ariel', 72, 'bold'),
bg='gold',
fg='white')
zClock.pack(fill=BOTH, expand=1)


def zTimer():
zClock.config(text=time.strftime('%H:%M:%S'))
zClock.after(500, zTimer)


zTimer()
zProgram.mainloop()


While I could have written the above in even fewer lines using Turtle Graphics, having just cobbled-together a training offering on the same I thought that using TK would make for a refreshingly different blog post.


Here is a link to zVideo :-)


Enjoy the Journey!

-Rn

p.s: Feel free to add more features (date, day... temperature probe support for your Raspberry Pi) as your time and obsession(s) may allow.



[ add comment ] ( 154 views )   |  permalink  |  related link

<<First <Back | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | Next> Last>>