Assuming you mean final as applied to methods, the two are basically opposites due to default virtualness. In C++, member functions are not virtual by default, so the virtual keyword is used to enable virtual behavior. In Java, methods are virtual by default, so the final keyword is used to disable virtual behavior.

To make an example of the difference via implementation--

#include <iostream>
#include <memory>

using std::cout;
using std::cin;
using std::ostream;
using std::auto_ptr;

template<bool>class B;
template<bool>class C;
template<bool>class D;

class A{
    public:
        ostream& run(ostream& out = cout){
            return out << "Class A\n";
        }
};

template<> // when true, run is virtual, when false run is not virtual
class B<true> : public A{
    public:
        virtual ostream& run(ostream& out = cout){
            return out << "Class B\n";
        }
};

template<>
class B<false> : public A{
    public:
        ostream& run(ostream& out = cout){
            return out << "Class B\n";
        }
};

template<> // when true, run is virtual. When false, run is non-virtual
class C<true> : public B<true>{
    public:
        virtual ostream& run(ostream& out = cout){
            return out << "Class C\n";
        }
};

template<>
class C<false> : public B<false>{
    public:
        ostream& run(ostream& out = cout){
            return out << "Class C\n";
        }
};

template<> // no difference between true and false in this case
class D<true> : public C<true>{
    public:
        ostream& run(ostream& out = cout){
            return out << "Class D\n";
        }
};

template<>
class D<false> : public C<false>{
    public:
        ostream& run(ostream& out = cout){
            return out << "Class D\n";
        }
};

int main(){

    auto_ptr< B<true> > test1 (new D<true>); // B virtual run is true
    auto_ptr< B<false> > test2 (new D<false>); // B virtual run is false (it isn't virtual)
    auto_ptr< B<true> > test3 (new C<true>); // B virtual run is true
    auto_ptr< B<false> > test4 (new C<false>); // B virtual run is false

    test1->run();
    test2->run();
    test3->run();
    test4->run();

    cout << "\n\n";

    D<true>* p1 = dynamic_cast< D<true>* >( test1.get() );
//    D<false>* p2 = dynamic_cast< D<false>* >( test2.get() ); // gives 'B<false> is not polymorphic type' error
    C<true>* p3 = dynamic_cast< C<true>* >( test3.get() );
//    C<false>* p4 = dynamic_cast< C<false>* >( test4.get() ); // gives 'B<false> is not polymorphic type' error

    p1->run();
//    p2->run();
    p3->run();
//    p4->run();

    cin.get();
    return 0;
}

...

import java.io.*;

public class NamespaceClass_1{

	public static void main(String... args){
		NamespaceClass_1 nsc1 = new NamespaceClass_1();
		NamespaceClass_1.A a1 = nsc1.new A(), a2 = nsc1.new B(),
						   a3 = nsc1.new C(), a4 = nsc1.new D();
		final OutputStream out = System.out;

		a4.run(a3.run(a2.run(a1.run(out)))); // Run til we run out! =P
	}

	class A{
		/*virtual*/ OutputStream run(OutputStream out){
			PrintStream ps = new PrintStream(out);
			ps.println("Class A");
			return ps;
		}
	}

	class B extends A{
		@Override final OutputStream run(OutputStream out){
			PrintStream ps = new PrintStream(out);
			ps.println("Class B");
			return ps;
		}
	}

	class C extends B{
		/*
		void run(OutputStream out){
			PrintStream ps = new PrintStream(out);
			ps.println("Class C");
		}*/ // cannot override final run method
	}

	class D extends C{
		/*
		void run(OutputStream out){
			PrintStream ps = new PrintStream(out);
			ps.println("Class D");
		}*/ // cannot override final run method
	}
}
This article has been dead for over six months. Start a new discussion instead.