C++ and virtual methods (for C# or Java programmers)

Last friday I stumbled over a seroius shortcomming of C++ (compared to C# or Java) I’d like to share here with you. It’s about virtual methods called from a class constructor.

The C# Example

Let me start with an example. Here’s some C# code that simply calls a virtual method (named test()) from the class’ constructor:

class TestBaseClass {
  public TestBaseClass() {
    Console.Write("From base class: ");
    test();
  }

  protected virtual void test() {
    Console.WriteLine("in base class");
  }
}

Creating an instance of this class results in nothing special:

From base class: in base class

Now lets create a sub class of TestBaseClass and override the virtual method:

class TestSubClass : TestBaseClass {
  public TestSubClass() {
    Console.Write("From sub class: ");
    test();
  }

  protected override void test() {
    Console.WriteLine("in sub class");
  }
}

Now, creating an instance of TestSubClass will print this:

From base class: in sub class
From sub class: in sub class

This means that the sub class’ implementation of test() was executed (and not TestBaseClass‘ implementation) – just as expected.

Note: In Java all methods are automatically virtual. In contrast to C# or C++ you can’t create “non-virtual” methods in Java.

The C++ Problem

And exactly here is the problem in C++. Let’s create a C++ version of the two classes above (compiled with Visual C++).

Header file (TestClass.h):

#pragma once

class TestBaseClass {
public:
  TestBaseClass();

protected:
  virtual void test();
};


class TestSubClass : public TestBaseClass {
public:
  TestSubClass();

protected:
  virtual void test();
};

Source file (TestClass.cpp):

#include "TestClass.h"
#include <stdio.h>

TestBaseClass::TestBaseClass() {
  printf("From base class: ");
  test();
}

void TestBaseClass::test() {
  printf("in base class\n");
}


TestSubClass::TestSubClass() : TestBaseClass() {
  printf("From sub class: ");
  test();
}

void TestSubClass::test() {
  printf("in sub class\n");
}

Now, creating an instance of TestSubClass results in the following output:

From base class: in base class
From sub class: in sub class

Note how the base class’ implementation of test() is used in the base class constructor while the sub class’ implementation of test() is used in the sub class constructor.

The problem here (in constrast to C# or Java) is that the sub class constructor hasn’t been executed yet and therefore the “redirection” from TestBaseClass::test() to TestSubClass::test() hasn’t been established yet.

Rule: There is no way to call a sub class’ implementation of a virtual function in the base class constructor!

The problem becomes even more severe with pure virtual (which is abstract in C# and Java) methods. These methods don’t even have an implementation in the base class and therefore can’t be executed at all.

For your interest: A C++/CLI class will behave like a C# class (and not like a C++ class).

Example Visual Studio Solution

I’ve created a solution (for Visual Studio 2010) containing the source code above. In addition to a C# and a C++ project, I’ve also added a C++/CLI project. You can download it here:

VirtualMethodTest.zip

How to add a radio station to iTunes

Predefined radio stations in the iTunes library

I love internet radio. And I love iTunes. So the next logical step would be for me to manage my favorite radio stations in iTunes – preferably in a special playlist only so that the radio stations don’t clutter up my iTunes library.

Now, iTunes comes out-of-the-box with some predefined radio stations. You can simply drag your favorite radio stations to your playlist. However, iTunes’ radio station list is far from complete. So it would be nice to be able to add new radio stations to iTunes.

The first thing you need is the URL to the live stream of the new radio station. Unfortunately, there is no way to add this URL to iTunes’ “Radio” section. Although there is the menu item “Open Stream…” (in the “Advanced” menu) that let’s you open any live stream, this live stream would be added to your iTunes library. Why is this a bad thing? Well, you can’t edit the meta data (eg. genre, title, artist, …) for live streams. If you stop a live stream and then play it again, the meta data will be reset to whatever the live stream tells iTunes. So you’ll end up with a lot genres in your genre list you don’t want to have.

Drag .pls file to iTunes playlist

The alternative is to add the live stream just to a playlist without adding it to your library. This is possible. Simply drag the live stream’s playlist file (with .pls file ending) to your iTunes playlist. This will add all entries in the playlist file to your iTunes playlist without adding them to your iTunes library. That’s it.

If you don’t have a playlist file but only the live stream’s URL, you can create a playlist file quite easily. Simply open your favorite plain text editor (note that Word will not work) and copy the following text:

[playlist]
File1=http://streamexample.com:80
Title1=My Favorite Online Radio
Length1=-1

NumberOfEntries=1

Version=2

Replace the values of File1 and Title1 with your live stream’s URL and name respectively and save the file as radio.pls. Now you can drag it to your iTunes playlist and you’re done.

"Repeat one" in iTunes

Hint: You may want to activate “Repeat One” (in iTunes lower left corner) for this playlist. This prevents iTunes from going to the next radio station in the list when there is a problem with the one currently playing.

VMWare Fusion Performance Test

Today I did some testing on the performance of VMWare Fusion 3.1 regarding whether to use a 32-bit or a 64-bit guest system on a 64-bit host system. For the test I used:

  • Machine: MacBook Pro 15” early 2010
  • CPU: Intel Cor i5 2.4 GHz (Dual Core; 64-bit CPU)
  • RAM: 4 GB 1067 MHz DDR3
  • OS: Mac OS X 10.6.5 (with all updates)
  • VMWare: VMWare Fusion 3.1.2 (332101)

For the testing I shut down all applications (that could be shut down) except for:

  • VMWare Fusion (of course)
  • Terminal
  • TextWrangler

I also disabled Spotlight indexing for the duration of the test using (in Terminal):

$ mdutil -a -i off  # use "-i on" to reenable indexing

For testing I used an Ubuntu 10.04 Server Edition Linux either in the x86 (32-bit) and in the x64 (64-bit) version. Each version got one CPU and 512 MB RAM assigned (default values). I installed all updates (as of 2010-12-17) and also installed the packages “psmisc” and “bc”. The kernel version was 2.6.32-26. The VMWare Tools were not installed.

I then started VMWare Fusion (Virtual Machine Library only for now), and then called “purge” in the Terminal to free all inactive, unused memory for more correct information on how much memory is actually free. I then ran “vm_stat” (in Terminal), started the virtual machine, and ran “vm_stat” again to get the amount of memory actually used by the virtual machine.

Inside the virtual machine (i.e. in Ubuntu) I stopped cron and rsyslog to prevent them from interrupting the test, determined the free disk space (df -h) and the free memory (free -ok), and then calculated Pi with 3000 digits:

$ time echo "scale=3000; 4*a(1)" | (bc -l >/dev/null)

The results of the comparison can be found in the table below:

32-bit 64-bit Difference on 64-bit
Time to calculate Pi: 9.585s 8.823s -7.9%
Memory consumption on the host system (MacOS): 482.3 MB 648.2 MB +34.4%
Total/Used/Free memory in the guest system (Ubuntu): 496.96 MB / 35.22 MB / 461.74 MB 493.62 MB / 126.89 MB / 366.73 MB +260.3% (used only)
Disk usage in the guest system (Ubuntu): 560 MB 581 MB +3.8%

Observations:

  • CPU speed: A 32-bit guest system on a 64-bit host system runs slower than a 64-bit guest system.
  • Memory consumption: 64-bit guest systems require significantly more memory on the host system and on the guest system. In fact on the guest system the memory consumption seem to tripple (for some unknown reasons).
  • Disk usage: As expected, disk usage is higher on a 64-bit system , but only slightly.

Conclusions: If memory consumption is an issue on your system (i.e. if you have not so much memory), then select a 32-bit guest system. It’ll be slightly slower but also consume less memory. If memory consumption is not an issue, select a 64-bit guest system.

Deaktivieren des horizontalen Scrollens bei Logitech

Wer wie ich eine der “neueren” Logitech-Mäusen besitzt, wird vielleicht manchmal davon angenervt sein, dass statt einem Mittelklick auf das Mausrad horizontal gescrollt wird; denn die neueren Mäuse unterstützen nicht nur vertikales Scrollen sondern auch horizontales Scrollen via Mausrad (indem man das Mausrad kippt).

Je nach Maus (bei mir ist es die Logitech MX 1100) ist der Druckpunkt für die mittlere Maustaste einfacher – oder wie bei mir – eher schwieriger zu treffen. Das macht sich besonders im Firefox bemerkbar, der seit Version 3.5 in der Tableiste auch horizontales Scrollen unterstützt (d.h. zusätzlich zum Scrollen mit dem Mausrad). Regelmäßig passierte es dabei, dass ich – statt einen Tab zu schließen – durch die Tableiste gescrollt bin. Und das ist äußerst nervig.

Zum Glück gibt es aber Abhilfe; denn die Aktion, die beim Kippen des Mausrads ausgeführt werden sollen, sind konfigurierbar – via SetPoint.

Deaktivieren des horizontalen Scrollens via SetPoint 

Wichtig hierbei ist, dass unter “Andere” die Option “Keine Aktion” ausgewählt hat. Wählt man stattdessen “Nicht zugewiesen” aus, kommt jedes Mal beim Drücken der Taste ein nerviger Dialog.

Falsche Zone für Netzlaufewerke nach Update auf IE8

IE8 sucks. Sicherlich keine absolut objektive Meinung, aber fragt mal die Leute, die Webseiten entwickeln, was sie vom Internet Explorer halten.

Nach dem ich vor einiger Zeit auf den IE8 geupdatet hatte, da dieser jetzt als "Wichtiges Update" gehandelt wird, bin ich auf ein sehr seltsames Problem gestoßen (System ist übrigens Windows XP SP3):

Sicherheitswarnung beim Öffnen einer Textdatei

Ich meine, ich kenne das ja irgendwie von Anwendungen – aber warum zum Geier kommt das beim Öffnen einer Textdatei? Welcher Schaden könnte denn von dieser Datei wohl ausgehen? Die Datei liegt übrigens auf einem ganz normalen Netzlaufwerk; lokal funktioniert alles wunderbar.

Etwas genervt habe ich das Internet dann nach diesem Problem durchforstet, hab aber nix hilfreiches gefunden. Heute ist mir dann folgendes in der Statuszeile meines Explorers (wohl gemerkt – nicht Internet Explorer, sondern der Windows Explorer) aufgefallen:

Zone im Windows Explorer

WTF? Wieder das Internet befragt, wieder nichts gefunden. Durch Zufall bin ich dann aber auf die Lösung gestoßen. Sie findet sich unter "Systemsteuerung" -> "Internetoptionen" (was auch immer das da drin zu suchen hat…) ->"Sicherheit". Dort wählt man "Lokales Intranet" aus und klickt auf "Sites".

Internetoptionen

Hier muss die Option "Intranetnetzwerk automatisch ermitteln" deaktiviert werden, da sie einfach nicht funktioniert. Alle anderen Optionen bleiben aktiviert.

intranet-einstellungen

Jetzt alles mit "OK" bestätigen, dann Windows Explorer Fenster neu geöffnet (F5 bringt evtl. nichts) et voila – alles wieder so, wie es sein soll.

Korrekte Zone im Windows Explorer